xref: /haiku/src/servers/app/DelayedMessage.h (revision bab64f65bb775dc23060e276f1f1c4498ab7af6c)
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