/*  $Id: socket_select.h,v 1.6 2003/10/14 15:52:13 mbn Exp $
**
**  ClanLib Game SDK
**  Copyright (C) 2003  The ClanLib Team
**  For a total list of contributers see the file CREDITS.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This library is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**  Lesser General Public License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
**
*/

#ifndef header_socket_select
#define header_socket_select

#if _MSC_VER > 1000
#pragma once
#endif

#ifdef WIN32
#include <winsock2.h> // This has to be included before <list> else winsock.h somehow is included
#endif

#include <list>
#include "API/Core/System/thread.h"

class CL_Thread;
class CL_Mutex;
class CL_EventTrigger_Socket;

class CL_SocketSelect : CL_Runnable
{
//! Construction:
public:
	//: Creates the socket select listener thread.
	CL_SocketSelect();

	//: Shut down socket select listener thread.
	virtual ~CL_SocketSelect();

//! Attributes:
public:

//! Operations:
public:
	//: Start a read listen for the socket.
	void listen_read(CL_EventTrigger_Socket *socket);

	//: Start a write listen for the socket.
	void listen_write(CL_EventTrigger_Socket *socket);

	//: Start a exception listen for the socket.
	void listen_exception(CL_EventTrigger_Socket *socket);

	//: Remove socket from the read listening.
	void remove_read(CL_EventTrigger_Socket *socket);

	//: Remove socket from the write listening.
	void remove_write(CL_EventTrigger_Socket *socket);

	//: Remove socket from the exception listening.
	void remove_exception(CL_EventTrigger_Socket *socket);

//! Implementation:
private:
	//: Make the socket select thread break its listen and check for updates.
	//- <p>This is used to make it start listening on new sockets, and stop listening
	//- on old sockets.</p>
	void signal_listen_thread();

	//: Socket select thread function.
	virtual void run();

	CL_Thread *listen_thread;
	CL_Mutex *mutex;
	volatile bool stop_thread;

	std::list<CL_EventTrigger_Socket*> read_sockets;
	std::list<CL_EventTrigger_Socket*> write_sockets;
	std::list<CL_EventTrigger_Socket*> exception_sockets;

#ifdef WIN32
	WSAEVENT signal_event;
#else
	int signal_pipes[2];
#endif
};

#endif
