1 /*
2 * Copyright 2015, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Joseph Groover <looncraz@looncraz.net>
7 */
8 #ifndef AS_DELAYED_MESSAGE_H
9 #define AS_DELAYED_MESSAGE_H
10
11
12 #include <ObjectList.h>
13 #include <OS.h>
14
15
16 //! Method by which to merge DelayedMessages with the same code.
17 enum DMMergeMode {
18 DM_NO_MERGE = 0, // Will send this message, and the other(s)
19 DM_MERGE_REPLACE = 1, // Replace older data with newer data
20 DM_MERGE_CANCEL = 2, // keeps older data, cancels this message
21 DM_MERGE_DUPLICATES = 3 // If data is the same, cancel new message
22 };
23
24
25 //! Merge-mode data-matching, set which data must match to merge messages.
26 enum {
27 DM_DATA_DEFAULT = 0, // Match all for DUPLICATES & none for REPLACE modes.
28 DM_DATA_1 = 1 << 0,
29 DM_DATA_2 = 1 << 1,
30 DM_DATA_3 = 1 << 2,
31 DM_DATA_4 = 1 << 3,
32 DM_DATA_5 = 1 << 4,
33 DM_DATA_6 = 1 << 5
34 };
35
36
37 //! Convenient delay definitions.
38 enum {
39 DM_MINIMUM_DELAY = 500ULL,
40 DM_SHORT_DELAY = 1000ULL,
41 DM_120HZ_DELAY = 8888ULL,
42 DM_60HZ_DELAY = 16666ULL,
43 DM_MEDIUM_DELAY = 15000ULL,
44 DM_30HZ_DELAY = 33332ULL,
45 DM_15HZ_DELAY = 66664ULL,
46 DM_LONG_DELAY = 100000ULL,
47 DM_QUARTER_SECOND_DELAY = 250000ULL,
48 DM_HALF_SECOND_DELAY = 500000ULL,
49 DM_ONE_SECOND_DELAY = 1000000ULL,
50 DM_ONE_MINUTE_DELAY = DM_ONE_SECOND_DELAY * 60,
51 DM_ONE_HOUR_DELAY = DM_ONE_MINUTE_DELAY * 60
52 };
53
54
55 class DelayedMessageData;
56
57
58 /*! \class DelayedMessage
59 \brief Friendly API for creating messages to be sent at a future time.
60
61 Messages can be sent with a relative delay, or at a set time. Messages with
62 the same code can be merged according to various rules. Each message can
63 have any number of target recipients.
64
65 DelayedMessage is a throw-away object, it is to be created on the stack,
66 Flush()'d, then left to be destructed when out of scope.
67 */
68 class DelayedMessage {
69 typedef void(*FailureCallback)(int32 code, port_id port, void* data);
70 public:
71 DelayedMessage(int32 code, bigtime_t delay,
72 bool isSpecificTime = false);
73
74 ~DelayedMessage();
75
76 // At least one target port is required.
77 bool AddTarget(port_id port);
78
79 // Merge messages with the same code according to the following
80 // rules and data matching mask.
81 void SetMerge(DMMergeMode mode, uint32 match = 0);
82
83 // Called for each port on which the message was failed to be sent.
84 void SetFailureCallback(FailureCallback callback,
85 void* data = NULL);
86
87 template <class Type>
88 status_t Attach(const Type& data);
89 status_t Attach(const void* data, size_t size);
90
91 template <class Type>
92 status_t AttachList(const BObjectList<Type>& list);
93
94 template <class Type>
95 status_t AttachList(const BObjectList<Type>& list,
96 bool* whichArray);
97
98 status_t Flush();
99
100 // Private
101 DelayedMessageData* HandOff();
Data()102 DelayedMessageData* Data() {return fData;}
103
104 private:
105 // Forbidden methods - these are one time-use objects.
106 void* operator new(size_t);
107 void* operator new[](size_t);
108
109 DelayedMessageData* fData;
110 bool fHandedOff;
111 };
112
113
114 // #pragma mark Implementation
115
116
117 template <class Type>
118 status_t
Attach(const Type & data)119 DelayedMessage::Attach(const Type& data)
120 {
121 return Attach(&data, sizeof(Type));
122 }
123
124
125 template <class Type>
126 status_t
AttachList(const BObjectList<Type> & list)127 DelayedMessage::AttachList(const BObjectList<Type>& list)
128 {
129 if (list.CountItems() == 0)
130 return B_BAD_VALUE;
131
132 status_t error = Attach<int32>(list.CountItems());
133
134 for (int32 index = 0; index < list.CountItems(); ++index) {
135 if (error != B_OK)
136 break;
137
138 error = Attach<Type>(*(list.ItemAt(index)));
139 }
140
141 return error;
142 }
143
144
145 template <class Type>
146 status_t
AttachList(const BObjectList<Type> & list,bool * which)147 DelayedMessage::AttachList(const BObjectList<Type>& list, bool* which)
148 {
149 if (list.CountItems() == 0)
150 return B_BAD_VALUE;
151
152 if (which == NULL)
153 return AttachList(list);
154
155 int32 count = 0;
156 for (int32 index = 0; index < list.CountItems(); ++index) {
157 if (which[index])
158 ++count;
159 }
160
161 if (count == 0)
162 return B_BAD_VALUE;
163
164 status_t error = Attach<int32>(count);
165
166 for (int32 index = 0; index < list.CountItems(); ++index) {
167 if (error != B_OK)
168 break;
169
170 if (which[index])
171 error = Attach<Type>(*list.ItemAt(index));
172 }
173
174 return error;
175 }
176
177
178 #endif // AS_DELAYED_MESSAGE_H
179