Пример #1
0
void TaskSchedular::AsyncWork(TaskRunner* runner) {
	Task* toExec = nullptr;
	TaskRunner::AsyncGetRunner() = runner;
	runner->id = std::this_thread::get_id();
	while (toExec || (toExec = AsyncGetWork(runner))) {
#ifdef NEX_TASK_SCHEDULAR_CHECKS
		String lastTask = toExec->_name;
		if (TaskSchedular::_doAllowTraces)	{
			OutStringStream str;
			str << "Worker: " << runner->_name << ", running task: " << lastTask;
			Trace(str.str());
		}
#endif
		toExec = TaskRunner::Execute(toExec);
#ifdef NEX_TASK_SCHEDULAR_CHECKS
		if (TaskSchedular::_doAllowTraces)	{
			OutStringStream str;
			str << "Worker: " << runner->_name << ", finished task: " << lastTask;
			Trace(str.str());
		}
#endif

	}
	// reliquish all tasks to someone else
	runner->Relinquish(this);
#ifdef NEX_TASK_SCHEDULAR_CHECKS
	if (TaskSchedular::_doAllowTraces)	{
		Trace(runner->_name + " finished.");
	}
#endif
}
Пример #2
0
TaskSchedular::TaskSchedular()  {

	quit.store(false, std::memory_order_relaxed);
	unsigned int c = std::max<uint32>(1, std::thread::hardware_concurrency()-1);
	// @todo might kill performance, we need a way to serialize
	// in case we dont have the hardware
	OutStringStream str;
	str << "Worker Count: " << c;
	Trace(str.str());
	runners.reserve(c);
	for(uint32 i = 0; i < c; ++i) {
		TaskRunner* r = NEX_NEW(TaskRunner(i+1));
#ifdef NEX_TASK_SCHEDULAR_CHECKS
		if (TaskSchedular::_doAllowTraces)	{
			OutStringStream str2;
			str2 << "Runner" << i;
			r->_name = str2.str();
		}
#endif
		runners.push_back(r);
	}

	mainThread = NEX_NEW(TaskRunner(c+1));
	mainThread->MakeMain();
	runners.push_back(mainThread);
#ifdef NEX_TASK_SCHEDULAR_CHECKS
	mainThread->_name = "Main";
#endif
	for(uint32 i = 0; i < runners.size()-1; ++i) {
		runners[i]->Start(this);
	}
}
Пример #3
0
void TaskSchedular::AsyncResume(Task* waitingOn, uint32 limit) {
	Task* toExec = nullptr;
	TaskRunner* runner = TaskRunner::AsyncGetRunner();
	while(waitingOn->meta.refCount.load(std::memory_order_relaxed) > (int)limit) {
		if (toExec ||
				(toExec = AsyncGetWork(runner, false))
			) {
#ifdef NEX_TASK_SCHEDULAR_CHECKS
			if (TaskSchedular::_doAllowTraces)	{
				OutStringStream str;
				str << "Waited: " << runner->_name << ", running task: " << toExec->_name;
				Trace(str.str());
			}
#endif
			toExec = TaskRunner::Execute(toExec);
		}
	}

	if (toExec) {
#ifdef NEX_TASK_SCHEDULAR_CHECKS
		
		NEX_ASSERT(toExec->meta.state == Task::TASK_QUEUED ||
				toExec->meta.state == Task::TASK_INIT);
		toExec->meta.state = Task::TASK_QUEUED;
#endif
		runner->AddTask(toExec);
	}
}
void HttpStringStreamTester::testWriteAllAtOnce(const SampleResponse &resp)
{
    InStringStream iss(sampleGetReq.GetRequest());
    OutStringStream oss;
    HttpStringStream hss(&iss, &oss);

    const std::string &response = resp.GetResponse();
    ssize_t bytes = hss.Write(response.data(), response.size());
    assert(bytes == response.size());
    assert(oss.GetOutput() == response);
}
Пример #5
0
void TaskSchedular::AsyncSubmit(Task* singleTask) {
	singleTask->PrepareSubmit();
	std::lock_guard<mutex_type> guard(lock);
#ifdef NEX_TASK_SCHEDULAR_CHECKS
	NEX_ASSERT(singleTask->meta.state == Task::TASK_QUEUED ||
			singleTask->meta.state == Task::TASK_INIT);
	singleTask->meta.state = Task::TASK_QUEUED;
	if (TaskSchedular::_doAllowTraces)	{
		OutStringStream str;
		str << "Submit to queue: " <<  "task: " << singleTask->_name;
		Trace(str.str());
	}
#endif

	submittedTasks.push_back(singleTask);
}
void HttpStringStreamTester::testWriteUptoFirstBodyByte(const SampleResponse &resp)
{
    // Response header should be buffered completed, only to be written out on Flush or first byte of body.

    InStringStream iss(sampleGetReq.GetRequest());
    OutStringStream oss;
    HttpStringStream hss(&iss, &oss);

    const std::string &response = resp.GetResponse();
    ssize_t bytes = hss.Write(response.data(), resp.GetAnsHeaderSize());
    assert(bytes == sampleGetResp.GetAnsHeaderSize());
    assert(oss.GetOutput().empty());

    bytes = hss.Write(response.data() + resp.GetAnsHeaderSize(), 1);
    assert(bytes == 1);
    assert(oss.GetOutput().compare(0, std::string::npos, response, 0, resp.GetAnsHeaderSize() + 1) == 0);
}
Пример #7
0
    String IpAddressV6::toString() const
    {
        OutStringStream oss;
        TextWriter textWriter(oss);

        for(std::size_t i = 0; i < getByteCount(); i++)
        {
            textWriter << at(i);

            if(i < getByteCount() - 1)
            {
                textWriter << ':';
            }
        }

        return oss.toString();
    }
Пример #8
0
void TaskSchedular::AsyncAddChildTask(Task* task) {
	NEX_ASSERT(task);
	task->PrepareSubmit();
	TaskRunner* runner = TaskRunner::AsyncGetRunner();
#ifdef NEX_TASK_SCHEDULAR_CHECKS
	if (TaskSchedular::_doAllowTraces)	{
		OutStringStream str;
		str << "Thread: " << runner->_name << ", task queue: "
				<< runner->requestQueue.Tail() << " via, " << task->_name;
		Trace(str.str());
	}
#endif
	runner->AddTask(task);
#ifdef NEX_TASK_SCHEDULAR_CHECKS
	task->meta.state = Task::TASK_QUEUED;
#endif
	runner->taskCount++;
}
void HttpStringStreamTester::testWriteOnlyHeader(const SampleResponse &resp)
{
    // Response header should be buffered completed, only to be written out on Flush or first byte of body.
    // Thus, if only the response buffer is written, nothing should be written out to the underlying stream.

    InStringStream iss(sampleGetReq.GetRequest());
    OutStringStream oss;
    HttpStringStream hss(&iss, &oss);

    const std::string &response = resp.GetResponse();
    ssize_t bytes = hss.Write(response.data(), resp.GetAnsHeaderSize());
    assert(bytes == resp.GetAnsHeaderSize());
    assert(oss.GetOutput().empty());

    int err = hss.Flush();
    assert(!err);
    std::string out = oss.GetOutput();
    assert(response.compare(0, out.size(), out) == 0);
}
Пример #10
0
void TaskSchedular::AsyncSubmit(Task** multipleTasks, uint32 n) {
	std::lock_guard<mutex_type> guard(lock);
#ifdef NEX_TASK_SCHEDULAR_CHECKS
	if (TaskSchedular::_doAllowTraces)	{
		OutStringStream str;
		str << "Submit: tasks " << n;
		Trace(str.str());
	}
	std::for_each(multipleTasks, multipleTasks+n, [] (Task* singleTask) {
		NEX_ASSERT(singleTask->meta.state == Task::TASK_QUEUED ||
						singleTask->meta.state == Task::TASK_INIT);
				singleTask->meta.state = Task::TASK_QUEUED;
	});
#endif
	std::for_each(multipleTasks, multipleTasks + n, [](Task* singleTask) {
		singleTask->PrepareSubmit();
	});
	submittedTasks.insert(submittedTasks.end(), multipleTasks, multipleTasks+n);
}
Пример #11
0
Task* TaskSchedular::AsyncGetWork(TaskRunner* runner, bool repeat) {
	// try to retrieve from own queue first
	Task* task = nullptr;
	do {
		task = runner->RetrieveTask();

		if (!task) {
			uint32 n = (uint32)runners.size();
			uint32 i = runner->laststeal;
			uint32 counter = 0;
			TaskRunner* neighbour;
			while( !task && (counter++) < n ) {
				neighbour = runners[(i++)%n];
				if (neighbour == runner)
					continue;
				task = neighbour->requestQueue.AsyncSteal();
			}
#ifdef NEX_TASK_SCHEDULAR_CHECKS
			if (task) {
				if (TaskSchedular::_doAllowTraces)	{
					OutStringStream str;
					str << "Stolen: " << runner->_name << " has stolen " << neighbour->_name << "'s task: " << task->_name;
					Trace(str.str());
				}
				runner->laststeal = i;
			}
#endif
		}

		if (!task) {
			// try to work on a submitted task
			if(lock.try_lock()) {
				if (submittedTasks.size()) {
					task = submittedTasks.back();
					submittedTasks.pop_back();
#ifdef NEX_TASK_SCHEDULAR_CHECKS
					if (task) {
						if (TaskSchedular::_doAllowTraces)	{
							OutStringStream str;
							str << "Dequed: " << runner->_name << " has fetched task: " << task->_name;
							Trace(str.str());
						}
					}
#endif
				}
				lock.unlock();
			}
		}

		if (!repeat || task) {
#ifdef NEX_TASK_SCHEDULAR_CHECKS
			// This check is problematic, as a task may be queued once,
			// Run is completed, by the time PrepareSubmit is called on it, 
			// the task may not have been marked as finished and it might
			// be marked so afterwards, thus the state might come up as
			// either Running or Finished here.
			if(task)
				NEX_ASSERT(task->meta.state == Task::TASK_QUEUED);
#endif
			return task;
		}
#ifdef NEX_TASK_SCHEDULAR_CHECKS
		if (TaskSchedular::_doAllowTraces)	{
			//OutStringStream str;
			//str << "Yieldx: " << runner->_name << " is yielding.";
			//Trace(str.str());
		}
#endif
		std::this_thread::yield();
	} while(!quit.load(std::memory_order_relaxed));
	return nullptr;
}
Пример #12
0
void Simulation::draw(render::Context& context)
{
    context.setStencilBuffer(getWorldSize().getWidth().value(), getWorldSize().getHeight().value());

    // Render modules
    m_modules.draw(*this, context);

    // Draw objects
    for (auto& obj : m_objects)
    {
        Assert(obj);
        if (obj->isVisible())
            obj->draw(context);
    }

#if defined(CECE_ENABLE_RENDER) && defined(CECE_ENABLE_BOX2D_PHYSICS) && defined(CECE_ENABLE_BOX2D_PHYSICS_DEBUG)
    if (isDrawPhysics())
        m_world.DrawDebugData();
#endif

#if CONFIG_RENDER_TEXT_ENABLE
    context.disableStencilBuffer();

    if (isSimulationTimeRender())
    {
        if (!m_font)
        {
            m_font.create(context, g_fontData);
            m_font->setSize(getFontSize());
        }

        OutStringStream oss;
        {
            auto time = getTotalTime().value();
            unsigned int seconds = time;
            unsigned int milliseconds = static_cast<unsigned int>(time * 1000) % 1000;

            const unsigned int hours = seconds / (60 * 60);
            seconds %= (60 * 60);
            const unsigned int minutes = seconds / 60;
            seconds %= 60;

            if (hours)
            {
                oss << std::setw(2) << std::setfill('0') << hours << ":";
                oss << std::setw(2) << std::setfill('0') << minutes << ":";
            }
            else if (minutes)
            {
                oss << std::setw(2) << std::setfill('0') << minutes << ":";
            }

            oss << std::setw(2) << std::setfill('0') << seconds << ".";
            oss << std::setw(3) << std::setfill('0') << milliseconds;
        }

        if (hasUnlimitedIterations())
        {
            oss << " (" << getIteration() << " / -)";
        }
        else
        {
            oss << " (" << getIteration() << " / " << getIterations() << ")";
        }

        m_font->draw(context, oss.str(), getFontColor());
    }
#endif
}