学院首页>操作系统>Linux>在Linux上处理共享对象的同步事件

在Linux上处理共享对象的同步事件

作者:oasis 来源:chinaitlab 添加时间:2006-5-26 14:02:11

在面向对象的系统中,当一个对象接收到一条消息时,可能会发生一系列的事件。通常,这些事件是以 同步(synchronous) 模式处理的:调用进程或向这个对象发送消息的线程在发送消息调用完成之前都会接收并处理一系列事件。然而,如果产生这些事件的对象是由多个进程进行共享并且保存在共享内存中时,情况就稍微有些不同了。

  本文将使用两种 C++ 设计模式来详细介绍这种情况,并使用一些样例代码来展示这种解决方案(这些样例代码可以从本文 下载 一节中获得):

  1. 我们将简要介绍不使用共享内存的样例代码。

  2. 使用第一种设计模式来修改这些代码,让其使用共享内存。

  3. 然后阐述如何使用第二种设计模式来实现进程间通信(IPC)。

  您可以在任何机器体系架构、操作系统和编译器上应用这两种设计模式中的概念。对于本文来说,我们使用的是 RedHat Linux 7.1 for 32-bit x86 Intel® 体系架构的发行版;使用 GNU C++ compiler version 3.2.3 编译器及其相关工具来编译并测试样例程序。

  不使用共享内存

  下面让我们开始介绍这个样例程序,首先是不使用共享内存的程序:

  清单 1. common.h

#ifndef __COMMON_H__

#define __COMMON_H__

class IObjectWithEvents

{

public:

class IEventSink

{

public:

virtual void OnEvent(pid_t pid, const char * msg) = 0;

};

static IObjectWithEvents * getInstance();

virtual bool AddEventHandler(IEventSink * pEI) = 0;

virtual void SendMessage() = 0;

};

#endif //__COMMON_H__


  接口类 IObjectWithEvents 包含了一个内嵌的接口类 IEventSink,它定义了 OnEvent() 方法。这个事件处理程序接收一个发送者的 id 和一个字符串消息。getInstance() 方法返回对共享内存中对象的引用,AddEventHandler() 注册一个事件处理程序,SendMessage() 向这个对象发送一条消息。由于不需要引用共享内存,所以可以像清单 2 中那样来使用 IObjectWithEvents:


  清单 2. shm-client1.cpp

#include 

#include

#include

#include "common.h"

#define HERE __FILE__ << ":" << __LINE__ << " "

using namespace std;

class EventSink : public IObjectWithEvents::IEventSink

{

public:

void OnEvent(pid_t pid, const char * msg)

{

cout << HERE << "Message from pid(" << pid << ")\t : "
<< msg << endl;

}

};

int main()

{

IObjectWithEvents * powe = IObjectWithEvents::getInstance();

EventSink sink;

powe->AddEventHandler(&sink);

powe->SendMessage();

return 0;

}


  类 EventSink 提供了这个事件处理程序的实现。主函数中给出了用于发送消息和处理事件的标准序列。

  ObjectWithEvents 的典型实现如清单 3、4 所示:


  清单 3. ObjectWithEvents.h

#include "common.h"

class ObjectWithEvents : public IObjectWithEvents

{

public:

// We assume singleton design pattern for illustration

static ObjectWithEvents * ms_pObjectWithEvents;

ObjectWithEvents();

//the implementation for IObjectWithEvents

void FireEvent();

virtual bool AddEventHandler(IEventSink * pEI);

virtual void SendMessage();

//Collection for maintaining events

enum { MAX_EVENT_HANDLERS = 16, };

long m_npEI;

IEventSink * m_apEI[MAX_EVENT_HANDLERS];

pid_t m_alPID[MAX_EVENT_HANDLERS];

};

  清单 4. ObjectWithEvents.cpp

#include 

#include

#include

#include

#include

#include "ObjectWithEvents.h"


using namespace std;

ObjectWithEvents * ObjectWithEvents::ms_pObjectWithEvents = NULL;

IObjectWithEvents * IObjectWithEvents::getInstance()

{

// the following commented code is for illustration only.

/*

if (NULL == ObjectWithEvents::ms_pObjectWithEvents)

{

ObjectWithEvents::ms_pObjectWithEvents = new ObjectWithEvents();

}

*/

return ObjectWithEvents::ms_pObjectWithEvents;

}

ObjectWithEvents::ObjectWithEvents() : m_npEI(0)

{

}

void ObjectWithEvents::FireEvent()

{

// iterate through the collection

for (long i = 0; i < m_npEI; i++)

{

//Recheck for NULL

if (0 != m_apEI[i])

{

// Fire the event

m_apEI[i]->OnEvent(m_alPID[i], "");

}

}

return;

}

bool ObjectWithEvents::AddEventHandler(IEventSink * pEI)

{

// NULL check

if (NULL == pEI)

{

return false;

}

// check if there is space for this event handler

if (MAX_EVENT_HANDLERS == m_npEI)

{

return false;

}

// Add this event handler to the collection

m_alPID[m_npEI] = getpid();

m_apEI[m_npEI++] = pEI;

return true;

}

void ObjectWithEvents::SendMessage()

{

//Some processing

//And then fire the event

FireEvent();

return;

}

站内搜索