RunLoop::EventSourcePtr AsyncPipe::AsyncEventSource()
{
    return RunLoop::EventSource::New([this](RunLoop::EventSource&) {
        // atomically pull out the event flags here
        ThreadEvent t = _event.exchange(Wait);
        if ( t == Wait )
            return;
        
        if ( (t & Exceptional) == Exceptional )
        {
            // fire our own item
            if ( _eventDispatchSource != nullptr && _targetRunLoop != nullptr )
            {
                _eventDispatchSource->Signal();
            }
            else if ( bool(_eventHandler) )
            {
                if ( _err != 0 ) {
                    _eventHandler(AsyncEvent::ErrorOccurred, this);
                } else if ( _eof != 0 ) {
                    _eventHandler(AsyncEvent::EndEncountered, this);
                }
            }
        }
        
        bool hasRead = false, hasWritten = false;
        
        if ( (t & ReadSpaceAvailable) == ReadSpaceAvailable )
        {
            // data pulled out of here, so room to write there
            hasRead = true;
        }
        if ( (t & DataToWrite) == DataToWrite )
        {
            hasWritten = true;
        }
        
        auto counterpart = _counterpart.lock();
        if ( (hasRead || hasWritten) && bool(counterpart) )
        {
            auto source = counterpart->_eventDispatchSource;
            if ( bool(source) && !source->IsCancelled() )
            {
                source->Signal();
            }
            else
            {
                auto handler = counterpart->_eventHandler;
                if ( bool(handler) ) {
                    if ( hasRead ) {
                        handler(AsyncEvent::HasSpaceAvailable, counterpart.get());
                    }
                    if ( hasWritten ) {
                        handler(AsyncEvent::HasBytesAvailable, counterpart.get());
                    }
                }
            }
        }
    });
}
RunLoop::EventSourcePtr AsyncByteStream::EventDispatchSource()
{
    return RunLoop::EventSource::New([this](RunLoop::EventSource&) {
        if ( _err != 0 )
        {
            if ( bool(_eventHandler) )
                _eventHandler(AsyncEvent::ErrorOccurred, this);
            if ( bool(_eventDispatchSource) )
                _eventDispatchSource->Cancel();
            if ( bool(_eventSource) )
                _eventSource->Cancel();
            return;
        }
        if ( _eof )
        {
            if ( bool(_eventHandler) )
                _eventHandler(AsyncEvent::EndEncountered, this);
            if ( bool(_eventDispatchSource) )
                _eventDispatchSource->Cancel();
            if ( bool(_eventSource) )
                _eventSource->Cancel();
            return;
        }
        
        if ( BytesAvailable() && bool(_eventHandler) )
            _eventHandler(AsyncEvent::HasBytesAvailable, this);
        if ( SpaceAvailable() && bool(_eventHandler) )
            _eventHandler(AsyncEvent::HasSpaceAvailable, this);
    });
}
Beispiel #3
0
void AsyncByteStream::InitAsyncHandler()
{
    if ( _asyncIOThread.joinable() )
        throw std::logic_error("The async IO thread already been started");
    
    _asyncIOThread = std::thread([&](){
        // atomically pull out the event flags here
        ThreadEvent t = _event.exchange(Wait);
        if ( t == Terminate )
        {
            return;
        }
        
        bool hasRead = false, hasWritten = false;
        
        uint8_t buf[4096];
        
        if ( (t & ReadSpaceAvailable) == ReadSpaceAvailable )
        {
            std::lock_guard<RingBuffer> _(_ringbuf);
            size_type read = this->read_for_async(buf, _ringbuf.SpaceAvailable());
            if ( read != 0 )
            {
                _ringbuf.WriteBytes(buf, read);
                hasRead = true;
            }
        }
        if ( (t & DataToWrite) == DataToWrite )
        {
            std::lock_guard<RingBuffer> _(_ringbuf);
            size_type written = _ringbuf.ReadBytes(buf, _ringbuf.BytesAvailable());
            written = this->write_for_async(buf, written);
            if ( written != 0 )
            {
                // only remove as much as actually went out
                _ringbuf.RemoveBytes(written);
                hasWritten = true;
            }
        }
        
        if ( hasRead )
            _eventHandler(AsyncEvent::HasBytesAvailable, this);
        if ( hasWritten )
            _eventHandler(AsyncEvent::HasSpaceAvailable, this);
        
        std::unique_lock<std::mutex> __l(_condMutex);
        _threadSignal.wait(__l, [&](){ return _event != Wait; });
    });
}
Beispiel #4
0
bool WgTablist::SelectTab( int id )
{
	WgTab * pTab = _findTab(id);

	if( pTab == m_pTabSelected )
		return true;				// Not an error...

	if( pTab )
	{

		m_pTabSelected = pTab;
		pTab->m_bAlert = false;		// Selecting automatically stops any alert.
		_resizeTabs();				// fonts have changed
		_requestRender();

		WgEventHandler * pHandler = _eventHandler();
		if( pHandler )
		{
			WgItemInfo * p = new WgItemInfo[1];
			p->id = pTab->m_id;						//TODO: Should set index too (and in the future, a pointer to the widget of the tab).

			pHandler->QueueEvent( new WgItemsSelectEvent(this, 1, p) );
		}
		return true;
	}

	_resizeTabs();		// fonts have changed
	_requestRender();

	return false;
}
bool WgPopupLayer::ClosePopup( const WgWidgetPtr& pWidget )
{
	if( !pWidget || pWidget->Parent() != this || pWidget == m_baseHook.Widget() )
		return false;

	WgEventHandler * pEH = _eventHandler();

	WgPopupHook * pHook = (WgPopupHook *) pWidget->_hook();

	while( pHook )
	{
		WgPopupHook * p = pHook;
		pHook = pHook->_next();

		if( pEH )
			pEH->QueueEvent( new WgPopupClosedEvent( p->_widget(), p->m_pOpener ) );

		p->_requestRender();
		delete p;
	}
	_restoreKeyboardFocus();
	return true;
}
Beispiel #6
0
void WgTablePanel::_updateMarkedRowColumn( int row, int column )
{
	// Update m_markedRow/Column right away so change has happened before signals are emitted.

	int oldRow		= m_markedRow;
	int oldColumn	= m_markedColumn;

	m_markedRow = row;
	m_markedColumn = column;

	//

	WgEventHandler * pHandler = _eventHandler();

	if( pHandler && (column != oldColumn || row != oldRow) )
	{
		if( oldRow != -1 && oldColumn != -1 )
			pHandler->QueueEvent( new WgEvent::TableCellUnmarked(this, oldRow, oldColumn, GetCellContent(oldRow, oldColumn) ) );

		if( row != -1 && column != -1 )
			pHandler->QueueEvent( new WgEvent::TableCellMarked(this, row, column, GetCellContent(row, column) ) );
	}
}
	void OpenGLWindow::gameLoop(){
		SDL_Event event;
		bool isRunning = true;
		//start the game loop
		while(isRunning){
			//check and handle for any events
			while(SDL_PollEvent(&event)){
				switch(event.type){
					//exit on escape key
					case SDL_KEYUP: if(event.key.keysym.sym == SDLK_ESCAPE) isRunning = false; break;
					//exit on close button pressed
					case SDL_QUIT: isRunning = false; break;
					//resize on resizing the window
					case SDL_VIDEORESIZE: 	setWidth(event.resize.w); setHeight(event.resize.h);
											setCanvas( SDL_SetVideoMode( width(), height() , 32 , flags() ) );
											(*_resizeFunc)(event.resize.w,event.resize.h); break;
				}
				//call additional event handler provided by user
				_eventHandler(event);
			}
			//render screen
			(*_renderFunc)();
		}
	}
Beispiel #8
0
void AsyncByteStream::InitAsyncHandler()
{
    if ( _eventSource != nullptr )
        throw std::logic_error("This stream is already set up for async operation.");
    
    Weak<RingBuffer> weakReadBuf = _readbuf;
    Weak<RingBuffer> weakWriteBuf = _writebuf;
    
    _eventSource = new RunLoop::EventSource([=](RunLoop::EventSource&) {
        // atomically pull out the event flags here
        ThreadEvent t = _event.exchange(Wait);
        
        bool hasRead = false, hasWritten = false;
        
        uint8_t buf[4096];
        
        Shared<RingBuffer> readBuf = weakReadBuf.lock();
        Shared<RingBuffer> writeBuf = weakWriteBuf.lock();
        
        if ( (t & ReadSpaceAvailable) == ReadSpaceAvailable && readBuf )
        {
            std::lock_guard<RingBuffer> _(*readBuf);
            size_type read = this->read_for_async(buf, readBuf->SpaceAvailable());
            if ( read != 0 )
            {
                readBuf->WriteBytes(buf, read);
                hasRead = true;
            }
        }
        if ( (t & DataToWrite) == DataToWrite && writeBuf )
        {
            std::lock_guard<RingBuffer> _(*writeBuf);
            size_type written = writeBuf->ReadBytes(buf, writeBuf->BytesAvailable());
            written = this->write_for_async(buf, written);
            if ( written != 0 )
            {
                // only remove as much as actually went out
                writeBuf->RemoveBytes(written);
                hasWritten = true;
            }
        }
        
        auto invocation = [this, hasRead, hasWritten] () {
            if ( hasRead )
                _eventHandler(AsyncEvent::HasBytesAvailable, this);
            if ( hasWritten )
                _eventHandler(AsyncEvent::HasSpaceAvailable, this);
        };
        
        if ( _targetRunLoop != nullptr )
        {
            _targetRunLoop->PerformFunction(invocation);
        }
        else
        {
            invocation();
        }
    });
    
    if ( _asyncRunLoop == nullptr )
    {
        std::mutex __mut;
        std::condition_variable __inited;
        
        std::unique_lock<std::mutex> __lock(__mut);
        _asyncIOThread = std::thread([&](){
            AsyncByteStream::_asyncRunLoop = RunLoop::CurrentRunLoop();
            {
                std::unique_lock<std::mutex> __(__mut);
                __inited.notify_all();
            }
            
            // now run the run loop
            
            // only spin an empty run loop a certain amount of time before giving up
            // and exiting the thread entirely
            // FIXME: There's a gap here where a race could lose an EventSource addition
            static constexpr unsigned kMaxEmptyTicks(1000);
            static constexpr std::chrono::milliseconds kTickLen(10);
            unsigned __emptyTickCounter = 0;
            
            do
            {
                RunLoop::ExitReason __r = RunLoop::CurrentRunLoop()->Run(true, std::chrono::seconds(20));
                if ( __r == RunLoop::ExitReason::RunFinished )
                {
                    if ( ++__emptyTickCounter == kMaxEmptyTicks )
                        break;      // exit the thread
                    
                    // wait a bit and try again
                    std::this_thread::sleep_for(kTickLen);
                }
                
                // by definition not an empty runloop
                __emptyTickCounter = 0;
            } while (1);
            
            // nullify the global before we quit
            // deletion isn't necessary, it's done by TLS in run_loop.cpp
            _asyncRunLoop = nullptr;
        });
        
        // wait for the runloop to be set
        __inited.wait(__lock, [&](){return _asyncRunLoop != nullptr;});
    }
    
    // install the event source into the run loop, then we're all done
    _asyncRunLoop->AddEventSource(_eventSource);
}
Beispiel #9
0
 bool event(SPEventContext *ec, GdkEvent *e) {
     return _eventHandler(ec, e);
 }
RunLoop::EventSourcePtr AsyncByteStream::AsyncEventSource()
{
    weak_ptr<RingBuffer> weakReadBuf = _readbuf;
    weak_ptr<RingBuffer> weakWriteBuf = _writebuf;
    
    return RunLoop::EventSource::New([=](RunLoop::EventSource&) {
        // atomically pull out the event flags here
        ThreadEvent t = _event.exchange(Wait);
        if ( t == Wait )
            return;
        
        bool hasRead = false, hasWritten = false;
        
        uint8_t buf[4096];
        
        shared_ptr<RingBuffer> readBuf = weakReadBuf.lock();
        shared_ptr<RingBuffer> writeBuf = weakWriteBuf.lock();
        
        if ( (t & ReadSpaceAvailable) == ReadSpaceAvailable && readBuf )
        {
            std::lock_guard<RingBuffer> _(*readBuf);
            size_type read = this->read_for_async(buf, readBuf->SpaceAvailable());
            if ( read != 0 )
            {
                readBuf->WriteBytes(buf, read);
                hasRead = true;
            }
            else
            {
                _eof = true;
            }
        }
        if ( (t & DataToWrite) == DataToWrite && writeBuf )
        {
            std::lock_guard<RingBuffer> _(*writeBuf);
            size_type written = writeBuf->ReadBytes(buf, writeBuf->BytesAvailable());
            written = this->write_for_async(buf, written);
            if ( written != 0 )
            {
                // only remove as much as actually went out
                writeBuf->RemoveBytes(written);
                hasWritten = true;
            }
            else
            {
                _eof = true;
            }
        }
        
        if ( _targetRunLoop != nullptr )
        {
            _eventDispatchSource->Signal();
        }
        else if ( bool(_eventHandler) )
        {
            if ( readBuf->HasData() )
                _eventHandler(AsyncEvent::HasBytesAvailable, this);
            if ( writeBuf->HasSpace() )
                _eventHandler(AsyncEvent::HasSpaceAvailable, this);
        }
    });
}