FXRollback.h

Go to the documentation of this file.
00001 /********************************************************************************
00002 *                                                                               *
00003 *                         Transaction Rollback Support                          *
00004 *                                                                               *
00005 *********************************************************************************
00006 *        Copyright (C) 2002,2003 by Niall Douglas.   All Rights Reserved.       *
00007 *       NOTE THAT I DO NOT PERMIT ANY OF MY CODE TO BE PROMOTED TO THE GPL      *
00008 *********************************************************************************
00009 * This code is free software; you can redistribute it and/or modify it under    *
00010 * the terms of the GNU Library General Public License v2.1 as published by the  *
00011 * Free Software Foundation EXCEPT that clause 3 does not apply ie; you may not  *
00012 * "upgrade" this code to the GPL without my prior written permission.           *
00013 * Please consult the file "License_Addendum2.txt" accompanying this file.       *
00014 *                                                                               *
00015 * This code is distributed in the hope that it will be useful,                  *
00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                          *
00018 *********************************************************************************
00019 * $Id:                                                                          *
00020 ********************************************************************************/
00021 
00022 #ifndef FXROLLBACK_H
00023 #define FXROLLBACK_H
00024 
00025 #include "fxdefs.h"
00026 
00027 namespace FX {
00028 
00029 class QMutex;
00030 
00156 class FXAPI FXRollbackBase
00157 {
00158     friend class FXRollbackGroup;
00159 protected:
00160     mutable bool dismissed;
00161     typedef void (FXRollbackBase::*calladdrtype)();
00162     calladdrtype calladdr;
00163     mutable QMutex *mutex;
00164     virtual FXRollbackBase *copy() const=0;
00165 public:
00166     FXRollbackBase(calladdrtype addr) : dismissed(false), calladdr(addr), mutex(0) { }
00167     ~FXRollbackBase() { if(!dismissed) makeCall(); }
00168     FXRollbackBase(const FXRollbackBase &o) : dismissed(o.dismissed), calladdr(o.calladdr), mutex(o.mutex) { o.dismiss(); }
00170     void dismiss() const throw() { dismissed=true; }
00172     void setMutex(QMutex *m) const throw() { mutex=m; }
00174     void setMutex(QMutex &m) const throw() { mutex=&m; }
00175 private:
00176     void makeCall();
00177 
00178     // No, you really can't do this. Use FXRollbackGroup!
00179     FXRollbackBase &operator=(const FXRollbackBase &);
00180 };
00181 typedef const FXRollbackBase &FXRBOp;
00186 class FXRollbackGroup
00187 {
00188     void *list;
00189 public:
00190     FXRollbackGroup();
00191     ~FXRollbackGroup();
00193     void add(FXRollbackBase &item);
00195     void dismiss() const throw();
00196 };
00197 // For newed allocs
00198 template<typename par1> class FXRBNewI : public FXRollbackBase
00199 {
00200     par1 &mypar1;
00201     void call() { delete mypar1; mypar1=0; }
00202     virtual FXRollbackBase *copy() const { return new FXRBNewI<par1>(*this); }
00203 public:
00204     FXRBNewI(par1 &_par1) : mypar1(_par1), FXRollbackBase((calladdrtype) &FXRBNewI<par1>::call) { }
00205 };
00206 template<typename par1> FXRBNewI<par1> FXRBNew(par1 &_par1)
00207 {
00208     return FXRBNewI<par1>(_par1);
00209 }
00210 // For newed array allocs
00211 template<typename par1> class FXRBNewAI : public FXRollbackBase
00212 {
00213     par1 &mypar1;
00214     void call() { delete[] mypar1; mypar1=0; }
00215     virtual FXRollbackBase *copy() const { return new FXRBNewAI<par1>(*this); }
00216 public:
00217     FXRBNewAI(par1 &_par1) : mypar1(_par1), FXRollbackBase((calladdrtype) &FXRBNewAI<par1>::call) { }
00218 };
00219 template<typename par1> FXRBNewAI<par1> FXRBNewA(par1 &_par1)
00220 {
00221     return FXRBNewAI<par1>(_par1);
00222 }
00223 // For malloc,calloc allocs
00224 template<typename par1> class FXRBAllocI : public FXRollbackBase
00225 {
00226     par1 &mypar1;
00227     void call() { if(mypar1) free(mypar1); mypar1=0; }
00228     virtual FXRollbackBase *copy() const { return new FXRBAllocI<par1>(*this); }
00229 public:
00230     FXRBAllocI(par1 &_par1) : mypar1(_par1), FXRollbackBase((calladdrtype)&FXRBAllocI<par1>::call) { }
00231 };
00232 template<typename par1> FXRBAllocI<par1> FXRBAlloc(par1 &_par1)
00233 {
00234     return FXRBAllocI<par1>(_par1);
00235 }
00236 // For constructors
00237 template<class type> class FXRBConstructI : public FXRollbackBase
00238 {
00239     type *obj;
00240     class RedirDelete : public type
00241     {   // Some sugar to invoke our own operator delete
00242     public:
00243         RedirDelete() { }
00244         void operator delete(void *) throw() { /* do nothing */ }
00245     };
00246     void call()
00247     {
00248         RedirDelete *_obj=static_cast<RedirDelete *>(obj);
00249         delete _obj;
00250     }
00251     virtual FXRollbackBase *copy() const { return new FXRBConstructI<type>(*this); }
00252 public:
00253     FXRBConstructI(type *_obj) : obj(_obj), FXRollbackBase((calladdrtype) &FXRBConstructI<type>::call) { }
00254 };
00255 template<class type> FXRBConstructI<type> FXRBConstruct(type *obj)
00256 {
00257     return FXRBConstructI<type>(obj);
00258 }
00259 
00260 #ifdef DOXYGEN_SHOULD_SKIP_THIS
00261 
00264 FXRollbackOp FXRBFunc(function, [, par1 & [, par2 & [, par3 & [, par4 &]]]]);
00268 FXRollbackOp FXRBObj(object, ptrtomethod, [, par1 & [, par2 & [, par3 & [, par4 &]]]]);
00273 FXRollbackOp FXRBNew(ptrtonewedalloc &);
00278 FXRollbackOp FXRBNewA(ptrtonewedalloc &);
00283 FXRollbackOp FXRBAlloc(ptrtomem);
00287 FXRollbackOp FXRBConstruct(thisptr);
00288 #else
00289 // For 0 parameters
00290 template<typename func> class FXRBFuncI0 : public FXRollbackBase
00291 {
00292     func myfunc;
00293     void call() { if(myfunc) (*myfunc)(); }
00294     virtual FXRollbackBase *copy() const { return new FXRBFuncI0<func>(*this); }
00295 public:
00296     FXRBFuncI0(func _myfunc) : myfunc(_myfunc), FXRollbackBase((calladdrtype) &FXRBFuncI0<func>::call) { }
00297 };
00298 template<typename func> FXRBFuncI0<func> FXRBFunc(func _func)
00299 {
00300     return FXRBFuncI0<func>(_func);
00301 }
00302 // For 1 parameter
00303 template<typename func, typename par1> class FXRBFuncI1 : public FXRollbackBase
00304 {
00305     func myfunc;
00306     const par1 &mypar1;
00307     void call() { if(myfunc) myfunc(mypar1); }
00308     virtual FXRollbackBase *copy() const { return new FXRBFuncI1<func, par1>(*this); }
00309 public:
00310     FXRBFuncI1(func _myfunc, const par1 &_par1) : myfunc(_myfunc), mypar1(_par1), FXRollbackBase((calladdrtype) &FXRBFuncI1<func, par1>::call) { }
00311 };
00312 template<typename func, typename par1> FXRBFuncI1<func, par1> FXRBFunc(func _func, const par1 &_par1)
00313 {
00314     return FXRBFuncI1<func, par1>(_func, _par1);
00315 }
00316 // For 2 parameters
00317 template<typename func, typename par1, typename par2> class FXRBFuncI2 : public FXRollbackBase
00318 {
00319     func myfunc;
00320     const par1 &mypar1;
00321     const par2 &mypar2;
00322     void call() { if(myfunc) myfunc(mypar1, mypar2); }
00323     virtual FXRollbackBase *copy() const { return new FXRBFuncI2<func, par1, par2>(*this); }
00324 public:
00325     FXRBFuncI2(func _myfunc, const par1 &_par1, const par2 &_par2) : myfunc(_myfunc), mypar1(_par1), mypar2(_par2), FXRollbackBase((calladdrtype) &FXRBFuncI2<func, par1, par2>::call) { }
00326 };
00327 template<typename func, typename par1, typename par2> FXRBFuncI2<func, par1, par2> FXRBFunc(func _func, const par1 &_par1, const par2 &_par2)
00328 {
00329     return FXRBFuncI2<func, par1, par2>(_func, _par1, _par2);
00330 }
00331 // For 3 parameters
00332 template<typename func, typename par1, typename par2, typename par3> class FXRBFuncI3 : public FXRollbackBase
00333 {
00334     func myfunc;
00335     const par1 &mypar1;
00336     const par2 &mypar2;
00337     const par3 &mypar3;
00338     void call() { if(myfunc) myfunc(mypar1, mypar2, mypar3); }
00339     virtual FXRollbackBase *copy() const { return new FXRBFuncI3<func, par1, par2, par3>(*this); }
00340 public:
00341     FXRBFuncI3(func _myfunc, const par1 &_par1, const par2 &_par2, const par3 &_par3)
00342         : myfunc(_myfunc), mypar1(_par1), mypar2(_par2), mypar3(_par3), FXRollbackBase((calladdrtype) &FXRBFuncI3<func, par1, par2, par3>::call) { }
00343 };
00344 template<typename func, typename par1, typename par2, typename par3> FXRBFuncI3<func, par1, par2, par3> FXRBFunc(func _func, const par1 &_par1, const par2 &_par2, const par3 &_par3)
00345 {
00346     return FXRBFuncI3<func, par1, par2, par3>(_func, _par1, _par2, _par3);
00347 }
00348 // For 4 parameters
00349 template<typename func, typename par1, typename par2, typename par3, typename par4> class FXRBFuncI4 : public FXRollbackBase
00350 {
00351     func myfunc;
00352     const par1 &mypar1;
00353     const par2 &mypar2;
00354     const par3 &mypar3;
00355     const par4 &mypar4;
00356     void call() { if(myfunc) myfunc(mypar1, mypar2, mypar3, mypar4); }
00357     virtual FXRollbackBase *copy() const { return new FXRBFuncI4<func, par1, par2, par3, par4>(*this); }
00358 public:
00359     FXRBFuncI4(func _myfunc, const par1 &_par1, const par2 &_par2, const par3 &_par3, const par4 &_par4)
00360         : myfunc(_myfunc), mypar1(_par1), mypar2(_par2), mypar3(_par3), mypar4(_par4), FXRollbackBase((calladdrtype) &FXRBFuncI4<func, par1, par2, par3, par4>::call) { }
00361 };
00362 template<typename func, typename par1, typename par2, typename par3, typename par4> FXRBFuncI4<func, par1, par2, par3, par4> FXRBFunc(func _func, const par1 &_par1, const par2 &_par2, const par3 &_par3, const par4 &_par4)
00363 {
00364     return FXRBFuncI4<func, par1, par2, par3, par4>(_func, _par1, _par2, _par3, _par4);
00365 }
00366 
00367 // For 0 parameters
00368 template<class obj, typename method> class FXRBObjI0 : public FXRollbackBase
00369 {
00370     obj &myobj;
00371     method mymethod;
00372     void call() { if(mymethod) (myobj.*mymethod)(); }
00373     virtual FXRollbackBase *copy() const { return new FXRBObjI0<obj, method>(*this); }
00374 public:
00375     FXRBObjI0(obj &_myobj, method _mymethod)
00376         : myobj(_myobj), mymethod(_mymethod), FXRollbackBase((calladdrtype) &FXRBObjI0<obj, method>::call) { }
00377 };
00378 template<class obj, typename method> FXRBObjI0<obj, method> FXRBObj(obj &_obj, method _method)
00379 {
00380     return FXRBObjI0<obj, method>(_obj, _method);
00381 }
00382 // For 1 parameter
00383 template<class obj, typename method, typename par1> class FXRBObjI1 : public FXRollbackBase
00384 {
00385     obj &myobj;
00386     method mymethod;
00387     const par1 &mypar1;
00388     void call() { if(mymethod) (myobj.*mymethod)(mypar1); }
00389     virtual FXRollbackBase *copy() const { return new FXRBObjI1<obj, method, par1>(*this); }
00390 public:
00391     FXRBObjI1(obj &_myobj, method _mymethod, const par1 &_mypar1)
00392         : myobj(_myobj), mymethod(_mymethod), mypar1(_mypar1), FXRollbackBase((calladdrtype) &FXRBObjI1<obj, method, par1>::call) { }
00393 };
00394 template<class obj, typename method, typename par1> FXRBObjI1<obj, method, par1> FXRBObj(obj &_obj, method _method, const par1 &_par1)
00395 {
00396     return FXRBObjI1<obj, method, par1>(_obj, _method, _par1);
00397 }
00398 // For 2 parameters
00399 template<class obj, typename method, typename par1, typename par2> class FXRBObjI2 : public FXRollbackBase
00400 {
00401     obj &myobj;
00402     method mymethod;
00403     const par1 &mypar1;
00404     const par2 &mypar2;
00405     void call() { if(mymethod) (myobj.*mymethod)(mypar1, mypar2); }
00406     virtual FXRollbackBase *copy() const { return new FXRBObjI2<obj, method, par1, par2>(*this); }
00407 public:
00408     FXRBObjI2(obj &_myobj, method _mymethod, const par1 &_mypar1, const par2 &_mypar2)
00409         : myobj(_myobj), mymethod(_mymethod), mypar1(_mypar1), mypar2(_mypar2), FXRollbackBase((calladdrtype) &FXRBObjI2<obj, method, par1, par2>::call) { }
00410 };
00411 template<class obj, typename method, typename par1, typename par2> FXRBObjI2<obj, method, par1, par2> FXRBObj(obj &_obj, method _method, const par1 &_par1, const par2 &_par2)
00412 {
00413     return FXRBObjI2<obj, method, par1, par2>(_obj, _method, _par1, _par2);
00414 }
00415 // For 3 parameters
00416 template<class obj, typename method, typename par1, typename par2, typename par3> class FXRBObjI3 : public FXRollbackBase
00417 {
00418     obj &myobj;
00419     method mymethod;
00420     const par1 &mypar1;
00421     const par2 &mypar2;
00422     const par3 &mypar3;
00423     void call() { if(mymethod) (myobj.*mymethod)(mypar1, mypar2, mypar3); }
00424     virtual FXRollbackBase *copy() const { return new FXRBObjI3<obj, method, par1, par2, par3>(*this); }
00425 public:
00426     FXRBObjI3(obj &_myobj, method _mymethod, const par1 &_mypar1, const par2 &_mypar2, const par3 &_mypar3)
00427         : myobj(_myobj), mymethod(_mymethod), mypar1(_mypar1), mypar2(_mypar2), mypar3(_mypar3), FXRollbackBase((calladdrtype) &FXRBObjI3<obj, method, par1, par2, par3>::call) { }
00428 };
00429 template<class obj, typename method, typename par1, typename par2, typename par3> FXRBObjI3<obj, method, par1, par2, par3> FXRBObj(obj &_obj, method _method, const par1 &_par1, const par2 &_par2, const par3 &_par3)
00430 {
00431     return FXRBObjI3<obj, method, par1, par2, par3>(_obj, _method, _par1, _par2, _par3);
00432 }
00433 // For 4 parameters
00434 template<class obj, typename method, typename par1, typename par2, typename par3, typename par4> class FXRBObjI4 : public FXRollbackBase
00435 {
00436     obj &myobj;
00437     method mymethod;
00438     const par1 &mypar1;
00439     const par2 &mypar2;
00440     const par3 &mypar3;
00441     const par4 &mypar4;
00442     void call() { if(mymethod) (myobj.*mymethod)(mypar1, mypar2, mypar3, mypar4); }
00443     virtual FXRollbackBase *copy() const { return new FXRBObjI4<obj, method, par1, par2, par3, par4>(*this); }
00444 public:
00445     FXRBObjI4(obj &_myobj, method _mymethod, const par1 &_mypar1, const par2 &_mypar2, const par3 &_mypar3, const par4 &_mypar4)
00446         : myobj(_myobj), mymethod(_mymethod), mypar1(_mypar1), mypar2(_mypar2), mypar3(_mypar3), mypar4(_mypar4), FXRollbackBase((calladdrtype) &FXRBObjI4<obj, method, par1, par2, par3, par4>::call) { }
00447 };
00448 template<class obj, typename method, typename par1, typename par2, typename par3, typename par4> FXRBObjI4<obj, method, par1, par2, par3, par4> FXRBObj(obj &_obj, method _method, const par1 &_par1, const par2 &_par2, const par3 &_par3, const par4 &_par4)
00449 {
00450     return FXRBObjI4<obj, method, par1, par2, par3, par4>(_obj, _method, _par1, _par2, _par3, _par4);
00451 }
00452 #endif
00453 
00454 } // namespace
00455 
00456 #endif

(C) 2002-2009 Niall Douglas. Some parts (C) to assorted authors.
Generated on Fri Nov 20 18:31:24 2009 for TnFOX by doxygen v1.4.7