-
Notifications
You must be signed in to change notification settings - Fork 5
/
messagesystem.pas
120 lines (97 loc) · 2.69 KB
/
messagesystem.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
unit messagesystem;
{$mode objfpc}
interface
uses
Classes, SysUtils;
//there was a reason that this is crap...
type TMessageSystem = class
private
messageAccessSection: TRTLCriticalSection;
list: TFPList;
public
//synchronized methodes
procedure storeMessage(mes: TObject);
function retrieveMessageOrNil:TObject; //returns nil if no message exists
function retrieveLatestMessageOrNil:TObject; //returns nil if no message exists
function waitForMessage:TObject;
function existsMessage: boolean;
procedure removeAndFreeAll;
function openDirectMessageAccess: TFPList; //will block every access until close
procedure closeDirectMessageAccess(dlist: TFPList);
//not synchronized
constructor create;
destructor destroy;override;
end;
implementation
{ TMessageSystem }
procedure TMessageSystem.storeMessage(mes: TObject);
begin
if mes=nil then raise exception.Create('Tried to store not existing message in the message queue');
EnterCriticalSection(messageAccessSection);
list.add(mes);
LeaveCriticalSection(messageAccessSection);
end;
function TMessageSystem.retrieveMessageOrNil: TObject;
begin
EnterCriticalSection(messageAccessSection);
if list.Count=0 then result:=nil
else begin
result:=tobject(list[0]);
list.delete(0);
end;
LeaveCriticalSection(messageAccessSection);
end;
function TMessageSystem.retrieveLatestMessageOrNil: TObject;
begin
EnterCriticalSection(messageAccessSection);
if list.Count=0 then result:=nil
else begin
result:=tobject(list[list.count-1]);
list.delete(list.count-1);
end;
LeaveCriticalSection(messageAccessSection);
end;
function TMessageSystem.waitForMessage: TObject;
begin
Result:=nil;
while result = nil do begin
while not existsMessage do sleep(20);
result:=retrieveMessageOrNil; //list.count=0 is possible
end;
end;
function TMessageSystem.existsMessage: boolean;
begin
result:=list.Count>0;
ReadBarrier;
end;
procedure TMessageSystem.removeAndFreeAll;
var i:longint;
begin
EnterCriticalSection(messageAccessSection);
for i:=0 to list.Count-1 do
tobject(list[i]).free;
list.clear;
LeaveCriticalSection(messageAccessSection);
end;
function TMessageSystem.openDirectMessageAccess: TFPList;
begin
EnterCriticalSection(messageAccessSection);
Result:=list;
end;
procedure TMessageSystem.closeDirectMessageAccess(dlist: TFPList);
begin
LeaveCriticalSection(messageAccessSection);
if self.list<>dlist then raise Exception.Create('Invalid List');
end;
constructor TMessageSystem.create;
begin
InitCriticalSection(messageAccessSection);
list:=TFPList.Create;
end;
destructor TMessageSystem.destroy;
begin
DoneCriticalsection(messageAccessSection);
list.free;
inherited destroy;
end;
end.