Advertisement
Guest User

Untitled

a guest
Dec 17th, 2014
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.99 KB | None | 0 0
  1. struct Base
  2. {
  3. struct IFormat
  4. {
  5. virtual int formatVal(string &) = 0;
  6. };
  7.  
  8. void addFmt(IFormat * fmt)
  9. {
  10. if (!fmts.contains(fmt))
  11. fmts.push_back(fmt);
  12. }
  13.  
  14. void removeFmt(IFormat * fmt)
  15. {
  16. auto it = fmts.find(fmt);
  17. if (it != fmts.end())
  18. fmts.erase(it);
  19. }
  20.  
  21. int getValueFromFmts(string & input)
  22. {
  23. // this is getting called once in a while
  24. int ret(0);
  25. for (auto fmt : fmts)
  26. ret += fmt->formatVal(input);
  27. }
  28.  
  29. virtual ~Base()
  30. {
  31. // what now? something probably has a reference to me.
  32. }
  33. private:
  34. vector<IFormat *> fmts;
  35.  
  36. };
  37.  
  38.  
  39. struct Editor : public Base::IFormat
  40. {
  41. Editor(Base * base)
  42. : base(base)
  43. {
  44. base->addFmt(this);
  45. }
  46.  
  47. ~Editor()
  48. {
  49. // base might be deleted!
  50. base->removeFmt(this);
  51. }
  52.  
  53. virtual int formatVal(string &) override { ... }
  54.  
  55. private:
  56. Base * base;
  57. };
  58.  
  59. template<typename Derived>
  60. class DestructionServer
  61. {
  62. public:
  63. typedef Derived type;
  64.  
  65. class ObjectProxy
  66. {
  67. public:
  68. ObjectProxy(const Derived * serverToPresent)
  69. : server(serverToPresent)
  70. {}
  71.  
  72. bool operator == (const Derived * other) const
  73. {
  74. return server == other;
  75. }
  76.  
  77. bool operator != (const Derived * other) const
  78. {
  79. return server != other;
  80. }
  81.  
  82. private:
  83. const Derived * server;
  84. };
  85.  
  86. class Client
  87. {
  88. friend class DestructionServer<Derived>;
  89. public:
  90. Client()
  91. : server(nullptr)
  92. {
  93.  
  94. }
  95.  
  96. typedef DestructionServer Server;
  97.  
  98. virtual ~Client()
  99. {
  100. if (server)
  101. server->removeClientDestructor(this);
  102. }
  103.  
  104. virtual void onObjectDestruction(const ObjectProxy & destroyedObject) = 0;
  105.  
  106. private:
  107. void onDestruction(const Derived * derivedServer)
  108. {
  109. if (!server)
  110. throw std::runtime_error("Fatal error: DestructionServer::Client has no server!");
  111. // derivedServer should be able to downcast to server, without conversion
  112. if (derivedServer != server)
  113. throw std::runtime_error("Fatal error: derivedServer does not derive from server!");
  114.  
  115. // forget reference to server
  116. server = nullptr;
  117. // return an unmodifiable reference to the server
  118. onObjectDestruction(derivedServer);
  119. }
  120. Server * server;
  121. };
  122.  
  123.  
  124. void removeClientDestructor(Client * client)
  125. {
  126. auto it = std::find(clients.begin(), clients.end(), client);
  127. if (it != clients.end())
  128. {
  129. clients.erase(it);
  130. }
  131. }
  132.  
  133. void addClientDestructor(Client * client)
  134. {
  135. if (client && !std::contains(clients, client))
  136. {
  137. clients.push_back(client);
  138. // this only happens if a client is loaded into multiple servers
  139. // or the client is trying to add itself multiple times to the same server.
  140. if (client->server)
  141. throw std::runtime_error("Fatal error: Client already has a server!");
  142. client->server = this;
  143. }
  144. }
  145.  
  146. virtual ~DestructionServer()
  147. {
  148. for (Client * client : clients)
  149. {
  150. // would like to use a dynamic_cast here to check the upcast,
  151. // but it is not possible since
  152. // ((Derived*)this) is actually deconstructed at this point...
  153. // or can static_cast handle this?
  154. // in effect this is UB, but it 'works'
  155. if (const Derived * derivedServer = static_cast<const Derived *>(this))
  156. {
  157. client->onDestruction(derivedServer);
  158. }
  159. else
  160. {
  161. // in fact, the typeid() shouldn't work as well, here?
  162. throw std::runtime_error(
  163. std::string("Fatal error: ") + typeid(this).name() +
  164. " doesn't derive from " + typeid(DestructionServer<Derived> *).name()
  165. );
  166. }
  167. }
  168.  
  169. }
  170. protected:
  171. // make it impossible to construct this class without
  172. // deriving from this class.
  173. DestructionServer() {};
  174.  
  175. private:
  176. std::vector<Client *> clients;
  177. };
  178.  
  179. struct Base : public DestructionServer<Base>
  180. {
  181. struct IFormat : public Client
  182. {
  183. virtual int formatVal(string &) = 0;
  184. };
  185.  
  186. void addFmt(IFormat * fmt)
  187. {
  188. if (!fmts.contains(fmt))
  189. fmts.push_back(fmt);
  190. }
  191.  
  192. void removeFmt(IFormat * fmt)
  193. {
  194. auto it = fmts.find(fmt);
  195. if (it != fmts.end())
  196. fmts.erase(it);
  197. }
  198.  
  199. int getValueFromFmts(string & input)
  200. {
  201. // this is getting called once in a while
  202. int ret(0);
  203. for (auto fmt : fmts)
  204. ret += fmt->formatVal(input);
  205. }
  206.  
  207. virtual ~Base()
  208. {
  209. // DestructionServer automatically notifies all
  210. // objects that set a formatter to this class.
  211. }
  212. private:
  213. vector<IFormat *> fmts;
  214.  
  215. };
  216.  
  217.  
  218. struct Editor : public Base::IFormat
  219. {
  220. Editor(Base * base)
  221. : base(base)
  222. {
  223. base->addFmt(this);
  224. }
  225.  
  226. ~Editor()
  227. {
  228. // base is now null if it is deleted
  229. if(base)
  230. base->removeFmt(this);
  231. }
  232.  
  233. virtual int formatVal(string &) override { ... }
  234. virtual void onObjectDestruction(const Base::ObjectProxy & object)
  235. {
  236. if (object == base)
  237. {
  238. // ok, base is destructed now. set it to null and go kill our self
  239. base = nullptr;
  240. delete this;
  241. }
  242. }
  243. private:
  244. Base * base;
  245. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement