00001 #ifndef QPID_SYS_COPYONWRITEARRAY_H
00002 #define QPID_SYS_COPYONWRITEARRAY_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "Mutex.h"
00026 #include <algorithm>
00027 #include <vector>
00028 #include <boost/shared_ptr.hpp>
00029
00030 namespace qpid {
00031 namespace sys {
00032
00037 template <class T>
00038 class CopyOnWriteArray
00039 {
00040 public:
00041 typedef boost::shared_ptr<const std::vector<T> > ConstPtr;
00042
00043 CopyOnWriteArray() {}
00044 CopyOnWriteArray(const CopyOnWriteArray& c) : array(c.array) {}
00045
00046 void add(T& t)
00047 {
00048 Mutex::ScopedLock l(lock);
00049 ArrayPtr copy(array ? new std::vector<T>(*array) : new std::vector<T>());
00050 copy->push_back(t);
00051 array = copy;
00052 }
00053
00054 bool remove(T& t)
00055 {
00056 Mutex::ScopedLock l(lock);
00057 if (array && std::find(array->begin(), array->end(), t) != array->end()) {
00058 ArrayPtr copy(new std::vector<T>(*array));
00059 copy->erase(std::find(copy->begin(), copy->end(), t));
00060 array = copy;
00061 return true;
00062 } else {
00063 return false;
00064 }
00065 }
00066
00067 template <class F>
00068 bool add_unless(T& t, F f)
00069 {
00070 Mutex::ScopedLock l(lock);
00071 if (array && find_if(array->begin(), array->end(), f) != array->end()) {
00072 return false;
00073 } else {
00074 ArrayPtr copy(array ? new std::vector<T>(*array) : new std::vector<T>());
00075 copy->push_back(t);
00076 array = copy;
00077 return true;
00078 }
00079 }
00080
00081 template <class F>
00082 bool remove_if(F f)
00083 {
00084 Mutex::ScopedLock l(lock);
00085 if (array && std::find_if(array->begin(), array->end(), f) != array->end()) {
00086 ArrayPtr copy(new std::vector<T>(*array));
00087 copy->erase(std::remove_if(copy->begin(), copy->end(), f), copy->end());
00088 array = copy;
00089 return true;
00090 }
00091 return false;
00092 }
00093
00094 template <class F>
00095 F for_each(F f)
00096 {
00097 ArrayPtr a;
00098 {
00099 Mutex::ScopedLock l(lock);
00100 a = array;
00101 }
00102 if (!a) return f;
00103 return std::for_each(a->begin(), a->end(), f);
00104 }
00105
00106 ConstPtr snapshot()
00107 {
00108 ConstPtr a;
00109 {
00110 Mutex::ScopedLock l(lock);
00111 a = array;
00112 }
00113 return a;
00114 }
00115
00116 private:
00117 typedef boost::shared_ptr< std::vector<T> > ArrayPtr;
00118 Mutex lock;
00119 ArrayPtr array;
00120 };
00121
00122 }}
00123
00124
00125
00126 #endif