Darwin-Streaming-Server/CommonUtilitiesLib/EventContext.h

181 lines
5.4 KiB
C
Raw Permalink Normal View History

/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: EventContext.h
Contains: An event context provides the intelligence to take an event
generated from a UNIX file descriptor (usually EV_RE or EV_WR)
and signal a Task.
*/
#ifndef __EVENT_CONTEXT_H__
#define __EVENT_CONTEXT_H__
#include "OSThread.h"
#include "Task.h"
#include "OSRef.h"
#if MACOSXEVENTQUEUE
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER
#include <sys/ev.h>
#else
#include "ev.h"
#endif
#else
#include "ev.h"
#endif
//enable to trace event context execution and the task associated with the context
#define EVENTCONTEXT_DEBUG 0
class EventThread;
class EventContext
{
public:
//
// Constructor. Pass in the EventThread you would like to receive
// events for this context, and the fd that this context applies to
EventContext(int inFileDesc, EventThread* inThread);
virtual ~EventContext() { if (fAutoCleanup) this->Cleanup(); }
//
// InitNonBlocking
//
// Sets inFileDesc to be non-blocking. Once this is called, the
// EventContext object "owns" the file descriptor, and will close it
// when Cleanup is called. This is necessary because of some weird
// select() behavior. DON'T CALL CLOSE ON THE FD ONCE THIS IS CALLED!!!!
void InitNonBlocking(int inFileDesc);
//
// Cleanup. Will be called by the destructor, but can be called earlier
void Cleanup();
//
// Arms this EventContext. Pass in the events you would like to receive
void RequestEvent(int theMask = EV_RE);
//
// Provide the task you would like to be notified
void SetTask(Task* inTask)
{
fTask = inTask;
if (EVENTCONTEXT_DEBUG)
{
if (fTask== NULL)
qtss_printf("EventContext::SetTask context=%p task= NULL\n", (void *) this);
else
qtss_printf("EventContext::SetTask context=%p task= %p name=%s\n",(void *) this,(void *) fTask, fTask->fTaskName);
}
}
// when the HTTP Proxy tunnels takes over a TCPSocket, we need to maintain this context too
void SnarfEventContext( EventContext &fromContext );
// Don't cleanup this socket automatically
void DontAutoCleanup() { fAutoCleanup = false; }
// Direct access to the FD is not recommended, but is needed for modules
// that want to use the Socket classes and need to request events on the fd.
int GetSocketFD() { return fFileDesc; }
enum
{
kInvalidFileDesc = -1 //int
};
protected:
//
// ProcessEvent
//
// When an event occurs on this file descriptor, this function
// will get called. Default behavior is to Signal the associated
// task, but that behavior may be altered / overridden.
//
// Currently, we always generate a Task::kReadEvent
virtual void ProcessEvent(int /*eventBits*/)
{
if (EVENTCONTEXT_DEBUG)
{
if (fTask== NULL)
qtss_printf("EventContext::ProcessEvent context=%p task=NULL\n",(void *) this);
else
qtss_printf("EventContext::ProcessEvent context=%p task=%p TaskName=%s\n",(void *)this,(void *) fTask, fTask->fTaskName);
}
if (fTask != NULL)
fTask->Signal(Task::kReadEvent);
}
int fFileDesc;
private:
struct eventreq fEventReq;
OSRef fRef;
PointerSizedInt fUniqueID;
StrPtrLen fUniqueIDStr;
EventThread* fEventThread;
Bool16 fWatchEventCalled;
int fEventBits;
Bool16 fAutoCleanup;
Task* fTask;
#if DEBUG
Bool16 fModwatched;
#endif
static unsigned int sUniqueID;
friend class EventThread;
};
class EventThread : public OSThread
{
public:
EventThread() : OSThread() {}
virtual ~EventThread() {}
private:
virtual void Entry();
OSRefTable fRefTable;
friend class EventContext;
};
#endif //__EVENT_CONTEXT_H__