/usr/share/cruisecontrol-bin-2.6.1/projects/qpid-trunk/cpp/src/qpid/sys/DeletionManager.h

00001 #ifndef _sys_DeletionManager_h
00002 #define _sys_DeletionManager_h
00003 
00004 /*
00005  *
00006  * Licensed to the Apache Software Foundation (ASF) under one
00007  * or more contributor license agreements.  See the NOTICE file
00008  * distributed with this work for additional information
00009  * regarding copyright ownership.  The ASF licenses this file
00010  * to you under the Apache License, Version 2.0 (the
00011  * "License"); you may not use this file except in compliance
00012  * with the License.  You may obtain a copy of the License at
00013  * 
00014  *   http://www.apache.org/licenses/LICENSE-2.0
00015  * 
00016  * Unless required by applicable law or agreed to in writing,
00017  * software distributed under the License is distributed on an
00018  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
00019  * KIND, either express or implied.  See the License for the
00020  * specific language governing permissions and limitations
00021  * under the License.
00022  *
00023  */
00024 
00025 #include <vector>
00026 #include <algorithm>
00027 #include <boost/shared_ptr.hpp>
00028 
00029 namespace qpid {
00030 namespace sys {
00031 
00032 struct deleter
00033 {
00034   template <typename T>
00035   void operator()(T* ptr){ delete ptr;}
00036 };
00037 
00054 template <typename H>
00055 class DeletionManager 
00056 {
00057 public:
00058     // Mark every thread as using the handle - it will be deleted
00059     // below after every thread marks the handle as unused
00060     static void markForDeletion(H* handle) {
00061         allThreadsStatuses.addHandle(shared_ptr(handle));
00062     }
00063     
00064     // Mark this thread is not using any handle -
00065     // handles get deleted here when no one else
00066     // is using them either 
00067     static void markAllUnusedInThisThread() {
00068         static __thread ThreadStatus* threadStatus = 0;
00069 
00070         // Thread local vars can't be dynamically constructed so we need
00071         // to check whether we've made it yet and construct it if not
00072         // (no locking necessary for the check as it's thread local!)
00073         if (!threadStatus) {
00074             threadStatus = new ThreadStatus;
00075             allThreadsStatuses.addThreadStatus(threadStatus);
00076         }
00077 
00078         ScopedLock<Mutex> l(threadStatus->lock);
00079         
00080         // The actual deletions will happen here when all the shared_ptr
00081         // ref counts hit 0 (that is when every thread marks the handle unused)
00082         threadStatus->handles.clear();
00083     }
00084 
00085 private:
00086     typedef boost::shared_ptr<H> shared_ptr;
00087 
00088     // In theory we know that we never need more handles than the number of
00089     // threads runnning so we could use a fixed size array. However at this point
00090     // in the code we don't have easy access to this information. 
00091     struct ThreadStatus
00092     {
00093         Mutex lock;
00094         std::vector<shared_ptr> handles;
00095     };
00096 
00097     class AllThreadsStatuses
00098     {
00099         Mutex lock;
00100         std::vector<ThreadStatus*> statuses;
00101 
00102         struct handleAdder
00103         {
00104             shared_ptr handle;
00105 
00106             handleAdder(shared_ptr h): handle(h) {}
00107         
00108             void operator()(ThreadStatus* ptr) {
00109                 ScopedLock<Mutex> l(ptr->lock);
00110                 ptr->handles.push_back(handle);
00111             }
00112         };
00113 
00114     public:
00115         // Need this to be able to do static initialisation
00116         explicit AllThreadsStatuses(int) {}
00117 
00118         ~AllThreadsStatuses() {
00119             ScopedLock<Mutex> l(lock);
00120             std::for_each(statuses.begin(), statuses.end(), deleter());
00121         }
00122 
00123         void addThreadStatus(ThreadStatus* t) {
00124             ScopedLock<Mutex> l(lock);
00125             statuses.push_back(t);
00126         }
00127 
00128         void addHandle(shared_ptr h) {
00129             ScopedLock<Mutex> l(lock);
00130             std::for_each(statuses.begin(), statuses.end(), handleAdder(h));
00131         }
00132     };
00133     
00134     static AllThreadsStatuses allThreadsStatuses;
00135 };
00136 
00137 }}
00138 #endif // _sys_DeletionManager_h

Generated on Thu Apr 10 11:08:18 2008 for Qpid by  doxygen 1.4.7