00001 // list.h 00002 00019 #pragma once 00020 00021 namespace mongo { 00022 00023 /* this class uses a mutex for writes, but not for reads. 00024 we can get fancier later... 00025 00026 struct Member : public List1<Member>::Base { 00027 const char *host; 00028 int port; 00029 }; 00030 List1<Member> _members; 00031 _members.head()->next(); 00032 00033 */ 00034 template<typename T> 00035 class List1 : boost::noncopyable { 00036 public: 00037 /* next() and head() return 0 at end of list */ 00038 00039 List1() : _head(0), _m("List1"), _orphans(0) { } 00040 00041 class Base { 00042 friend class List1; 00043 T *_next; 00044 public: 00045 T* next() const { return _next; } 00046 }; 00047 00048 T* head() const { return _head; } 00049 00050 void push(T* t) { 00051 scoped_lock lk(_m); 00052 t->_next = _head; 00053 _head = t; 00054 } 00055 00056 // intentionally leak. 00057 void orphanAll() { 00058 _head = 0; 00059 } 00060 00061 /* t is not deleted, but is removed from the list. (orphaned) */ 00062 void orphan(T* t) { 00063 scoped_lock lk(_m); 00064 T *&prev = _head; 00065 T *n = prev; 00066 while( n != t ) { 00067 prev = n->_next; 00068 n = prev; 00069 } 00070 prev = t->_next; 00071 if( ++_orphans > 500 ) 00072 log() << "warning orphans=" << _orphans << '\n'; 00073 } 00074 00075 private: 00076 T *_head; 00077 mongo::mutex _m; 00078 int _orphans; 00079 }; 00080 00081 };