! | Данная информация предназначена только только для IT-специалистов по системной интеграции модулей БИОСОФТ-М. (см. Руководства пользователя к программным продуктам) |
Для разделяемой между процессами памяти есть низкоуровневый класс, использование которого без базовых теоретических знаний паралельного программирования и практического опыта оного приведет к гарантированным дефектам трудновыявляемого характера.
Более безопасная альтернатива для часто встречающегося случая: Разделяемый буфер для передачи потоков сигналов между процессами. Циклический
Написал коментариев, которых все равно абсолютно недостаточно чтобы использовать класс безопасно!
// // CInterMem - Interprocess Shared Memory // // WARNING: This is a low-level object which is NOT protected automatically // from common lock problems, deadlocks and race conditions! // You MUST follow one of proven init scenarios to access the memory. // // Note template<> CInterMem* classes which provide a somewhat safer way // of sharing and automatically locking the data structures in simple cases. // // Common safe init sequence: // // 1) Call SetName() with a string constant unique to your app. // All CInterMem objects in the system with the same name // will refer to the same physical memory block. // This name is also used as the base for a mutex name for // locking exclusive access to the memory. // // Include the data format version in the name. Otherwise you are // going to get some obscure bugs when different versions of your app // are running together! // // ---- at this point memory is not allocated yet! ---- // // 2) Call Lock() or create a local CInterMem::LOCK object // to safely initialize the buffer with FillOnFirstAllocation() // later. // (Do NOT call FillOnFirstAllocation() yet!) // You must also lock now if you intend to use !IsAlreadyExisted() // as a valid initialization condition. // (Note how template<>s help you to init and lock in one step.) // // (You may find working examples where this lock call is missing. // This might not be a bug but a dangerous reliance on a // strict process intercommunication sequence which is assumed // or verified using other means. // Do NOT try to pull such a trick unless you know exactly // what you are doing and what the consequences are!) // // 3) Call SetSize() to allocate the memory. // All shared CInterMem objects with the same name must // have equal size. // (Although theoretically subsequent allocs may be able to // succeed allocating smaller memory blocks than the one allocated // first but do NOT try to rely on this in a volatile multiprocess // environment!) // // 4) Init the buffer with FillOnFirstAllocation() for simple byte-fill init. // For more complex init check IsAlreadyExisted() while still // locked (see (2)) and if shared memory had NOT existed before // the moment you had locked, then get the pointer and // init ALL bytes as appropriate to you application. // (Note how template<>s help you to init and lock in one step.) // // 5) Unlock if locked on the step (2) or allow LOCK destructor to release // the mutex. // // 6) Access the memory for reading and writing always checking pointers // for NULL and never forget to ensure proper synchronization! // (Lock()/LOCK in most cases) // class CInterMem : public object { void cx_flag_IgnoreOverloads(); public: CX_STATIC_CLASS_INFO(CInterMem); CInterMem(); CInterMem( // for use only by templates, ignore this, call methods! str name, int init_size = 0, int lock_timeout = 0); ~CInterMem(); virtual void OnExposeContent(CExpose* pExpose); // Name of a unique shared memory mapped file // All CInterMem objects with the same name refer to the same // physical memory block. // (Also used for internal mutex) // Example: "MyXxxxAppSignalArray_v2" void SetName( str name); // All shared CInterMem objects with the same name must // have equal size. bool SetSize( int size); // By default shared memory is not initialized! // YOU MUST LOCK THE BUFFER AFTER SetName()! void FillOnFirstAllocation( char byte); // UNSAFE! May leak memory! void DetachHandle(); // Make sure only single client accesses the shared buffer. // This is an essential synchronization measure but it is // NOT ALWAYS ENOUGH to ensure currect data access in an // application sharing multiple interdependent memory blocks. void Lock( int timeout); void Unlock(); // To ensure we do not forget to Unlock it is more reliable // to use a local LOCK object with the unlocking destructor. class LOCK { public: LOCK(CInterMem* m, int timeout); ~LOCK(); CInterMem* mem; }; // Get attributes str GetName() const; int GetSize() const; int IsAlreadyExisted(); // May return NULL on failure // DO NOT FORGET TO LOCK THE MEMORY! const char* _unsafe_GetPointer() const; char* _unsafe_GetPointer(); }; ...
Встроены в этот класс так что отдельных мутексов создавать не требуется.
Я буду по мере надобности обертывать его использование в практические прикладные примеры на все случаи жизни. см. 1й пост.