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(); 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 119 DelayedMessage::Attach(const Type& data) 120 { 121 return Attach(&data, sizeof(Type)); 122 } 123 124 125 template <class Type> 126 status_t 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 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