Presentation is loading. Please wait.

Presentation is loading. Please wait.

Area Detector Drivers Towards A Pattern Jon Thompson.

Similar presentations


Presentation on theme: "Area Detector Drivers Towards A Pattern Jon Thompson."— Presentation transcript:

1 Area Detector Drivers Towards A Pattern Jon Thompson

2 Contents 1.Original Practice 2.Exception Handling 1.Mutexes 2.NDArrays 3.ASYN Parameters 4.Stream I/O 5.Decomposition 6.State Machines 7.Vendor Library Interfacing

3 Typical Requirements Vendor SDK library (often a Windows DLL). Ability to switch to a simulation library for offline testing that is as complete as possible. Multithreaded calls to the SDK often not supported or just not mentioned. Logging of SDK calls for debugging/blame purposes.

4 Original Pattern It’s straightforward and simple to understand!

5 Things I Would Like to Improve Fault propagation and reporting. One class does everything and gets too large. Proliferation of flags that control operation. Keeping track of the Mutex Lock. Be more OO and C++. Conformance to the area detector defined API.

6 Exceptions To be able to throw exceptions, functions need to be made tolerant. C++ guarantees the execution of destructors as the stack is unwound during an exception throw. It should not be necessary to catch exceptions so that clean up can be performed before re-throwing them. Note lack of ‘finally’ clause in C++. Use objects to represent access to resources that need to be cleaned up and take advantage of the scoping rules. We need smart pointer variants for mutex locks, NDArray pointers, etc.

7 The Port Driver Mutex AnADDriver::someFunctionThatUsesTheLock() { TakeLock takeLock(this); // Code that does stuff with the lock on aFunctionThatNeedsTheLock(takeLock); } AnADDriver::aFunctionThatNeedsTheLock(TakeLock& takeLock) { // Do stuff with the lock { FreeLock freeLock(takeLock); // Do stuff with the lock freed } // Do more stuff with the lock taken } Example use:

8 TakeLock class class TakeLock { friend class FreeLock; public: TakeLock(asynPortDriver* driver, bool alreadyTaken=false); TakeLock(FreeLock& freeLock); ~TakeLock(); private: TakeLock(); TakeLock(const TakeLock& other); TakeLock& operator=(const TakeLock& other); asynPortDriver* driver; bool initiallyTaken; }; Functions that require the lock to be taken should have a TakeLock object in their signature, even if they don’t use it internally. Copy constructor and assignment operator declared private. This forces them to be passed around by reference. Destructor automatically calls callParamCallbacks?

9 FreeLock class Functions that must be called without the lock taken could have a FreeLock object in the signature. Copy constructor and assignment operator declared private. This forces them to be passed around by reference. class FreeLock { friend class TakeLock; public: FreeLock(TakeLock& takeLock); ~FreeLock(); private: FreeLock(); FreeLock(const FreeLock& other); FreeLock& operator=(const FreeLock& other); asynPortDriver* driver; };

10 NDArray Pointers Another smart pointer type class must be used to hold NDArray pointers. Automatically calls release in the destructor. Every time the array is copied, reserve is called. class NdArrayRef { public: NdArrayRef(); NdArrayRef(NDArray* array); NdArrayRef(const NdArrayRef& other); virtual ~NdArrayRef(); NdArrayRef& operator=(const NdArrayRef& other); operator NDArray*() const; private: NDArray* array; };

11 Asyn Parameters We currently write this kind of code: { TakeLock takeLock(this); param2 = param2 + param1; } { lock(); int p1, p2; getIntegerParam(handle1, &p1); getIntegerParam(handle2, &p2); setIntegerParam(handle2, p2+p1); callParamCallbacks(); unlock(); } We could write this (assuming paramx are objects): Or maybe this (which makes the locking requirement explicit): { TakeLock takeLock(this); param2.set(takeLock, param2.get(takeLock) + param1.get(takeLock)); }

12 Asyn Parameters A change notification mechanism is required. We could use templated functors to call a member function: class MyDriver: public ADDriver { protected: IntegerParam param1; void onP1Change(); }; MyDriver::MyDriver() : IntegerParam param1(this, “PARAM1”, new Notify (this, &MyDriver::onP1Change)) { } void MyDriver::onP1Change() { // Do what we need to do when P1 changes }

13 Asyn Parameters Need an abstract class so that the system can manipulate the functors without knowing the type of the target. class AbstractNotify { public: AbstractNotify() {} virtual void operator()() = 0; }; template class Notify: public AbstractNotify { public: Notify(Target* target, void (Target::*fn)()) : target(target), fn(fn) {} virtual void operator()() {(target->*fn)();} private: Target* target; void (Target::*fn)(); };

14 Use stream I/O? Wrap asynTrace inside an iostream object. Allows use of << operators to output trace information. This does mean that the strings are generated BEFORE the decision whether to output or not is made. Uses a mutex to prevent traces from different threads getting mixed up. No comment is made on the desirability of the << operator syntax. { TraceStream tracer(getAsynUser(), 0x0100); tracer << “Hello world: ”; for(int i=0; i<5; i++) { tracer << i << “ “; } tracer << std::endl; }

15 Main Class Too Big For many cameras, the main ADDriver derived class gets very large. Indicative that the decomposition of the problem could be better. First attempt not too successful as the three resulting classes were too closely coupled.

16 State Machines Do you end up with a collection of booleans controlling the operation of your software? Instead, use a state variable and draw the state transition diagram. Let’s define a class to represent state variables. The version above implements a thread in which events can be processed. The doTransition virtual function is where the state machine implementation sits.

17 State Machines Attempting to write code that obviously represents a state diagram int MyDriver::doTransition(StateMachine* sm, int state, int event) { switch(state) { case STATE1: if(event == EVENT1) { doStuff(); state = STATE2; } break; case STATE2: if(event == EVENT1) { if(withCond() == 0) { state = STATE1; } else { state = STATE2; } break; // etc... } return state; }

18 State Machines State transitions are all written in one place. It is a little clumsy though. What would we like to write? class Pco { public: Pco(); enum state_t {STATE1, STATE2}; enum event_t {EVENT1}; int doStuff(); int withCond(); StateMachine sm; }; Pco::Pco() { // curState, event, action function, next States sm.transition(STATE1, EVENT1, new Act (this, &Sm::doStuff), STATE2); sm.transition(STATE2, EVENT1, new Act (this, &Sm::withCond), STATE1, STATE2); // etc... }

19 Vendor Library Interface Abstract base class to control access to the device. Place to implement logging and convert return codes into exceptions. Derived classes for vendor library and simulation. Can isolate any OS specific things inside the vendor library derived class. Startup script creates the appropriate object. The intention is not to abstract the API. It can be a lot of typing though…

20 Conclusions An extended interface library to the existing area detector is emerging. Along with a usage pattern. Some things may be appropriate for integration into a future area detector. Some things are just my own personal hobby horses. C++11 could improve the notation in some places. Any questions?

21 File Operations Mixer Class All file handling related parts of asynNDArrayDriver are moved out into a separate class. The constructor of this class must take an asynNDArrayDriver pointer so that it can create the asyn parameters. Any class that wants to make use of file operations includes the file operations class in its base class list. The slightly awkward bit is that this class must call the file operations class writeOctet function from its own override of writeOctet (parameter objects with a notify system would eliminate this). That’s it. All features of the file operations class are now available to the user class in just the same way as they are now.


Download ppt "Area Detector Drivers Towards A Pattern Jon Thompson."

Similar presentations


Ads by Google