message.pp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. { The Computer Language Shootout
  2. http://shootout.alioth.debian.org
  3. contributed by Marc Weustink
  4. }
  5. program message;
  6. {$mode objfpc}{$h-}
  7. uses
  8. PThreads;
  9. var
  10. PostOffice: array[0..499] of record
  11. Queue: array[0..15] of Integer; // queuelength must be power of 2
  12. ReadIdx, WriteIdx: Integer;
  13. ReadSem, WriteSem: TSemaphore;
  14. end;
  15. ThreadAttr: TThreadAttr;
  16. ThreadFuncAddr: TStartRoutine;
  17. Sum: Integer = 0;
  18. FinishedSem: TSemaphore;
  19. procedure PostMessage(AIndex, AMessage: Integer);
  20. begin
  21. with PostOffice[AIndex] do begin
  22. sem_wait(WriteSem);
  23. Queue[WriteIdx] := AMessage;
  24. sem_post(ReadSem);
  25. WriteIdx := (WriteIdx + 1) and (Length(Queue) - 1);
  26. end;
  27. end;
  28. function ReadMessage(AIndex: Integer): Integer;
  29. begin
  30. with PostOffice[AIndex] do begin
  31. sem_wait(ReadSem);
  32. Result := Queue[ReadIdx];
  33. sem_post(WriteSem);
  34. ReadIdx := (ReadIdx + 1) and (Length(Queue) - 1);
  35. end;
  36. end;
  37. function ThreadFunc(ANum: PtrInt): Pointer; cdecl;
  38. var
  39. Value: Integer;
  40. Id: TThreadID;
  41. begin
  42. if ANum <> 0
  43. then pthread_create(@Id, @ThreadAttr, ThreadFuncAddr, Pointer(ANum-1));
  44. repeat
  45. Value := ReadMessage(ANum);
  46. if Value <> -1
  47. then begin
  48. Inc(Value);
  49. if ANum = 0
  50. then Inc(Sum, Value)
  51. else PostMessage(ANum-1, Value);
  52. end
  53. else begin
  54. if ANum = 0
  55. then sem_post(@FinishedSem)
  56. else PostMessage(ANum-1, Value);
  57. //Break;
  58. end;
  59. until False;
  60. end;
  61. var
  62. n, count: Integer;
  63. Id: TThreadId;
  64. begin
  65. Val(paramstr(1), count, n);
  66. if n <> 0 then exit;
  67. for n := 0 to High(PostOffice) do with PostOffice[n] do begin
  68. ReadIdx := 0;
  69. WriteIdx := 0;
  70. sem_init(@ReadSem, 0, 0);
  71. sem_init(@WriteSem, 0, Length(Queue));
  72. end;
  73. sem_init(FinishedSem, 0, 0);
  74. pthread_attr_init(@ThreadAttr);
  75. pthread_attr_setdetachstate(@ThreadAttr, 1);
  76. pthread_attr_setstacksize(@ThreadAttr, 1024 * 16);
  77. ThreadFuncAddr := TStartRoutine(@ThreadFunc);
  78. pthread_create(@Id, @ThreadAttr, ThreadFuncAddr, Pointer(High(PostOffice)));
  79. for n := 1 to count do
  80. PostMessage(High(PostOffice), 0);
  81. PostMessage(High(PostOffice), -1);
  82. sem_wait(FinishedSem);
  83. WriteLn(Sum);
  84. end.