Jump to content
  • Advertisement
Sign in to follow this  
GroZZleR

Game Engine Design - Kernel / Task problem...

This topic is 4726 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey all, I've hit a bit of a snag with my latest engine. I've opted for the Kernel / Task system. I'm also including a messaging system, which allows multiple tasks to react to application posted messages. For that reason, I cannot make every task a singleton, which is a bad design to begin with in my opinion. Regardless, the lack of singletons has kicked me in the ass anyways. In order to pause / resume / kill tasks, you have to be able to identify them. I have no such system and can only think of one. At first I thought that tasks could just have a static ID field to identify them. This works fine and dandy, but not when it comes time to actually identify the task. ;)
TaskManager.RemoveTask(VideoTask.ID); // This is OK

TaskManager :: RemoveTask(string ID)
{
     for(int i = 0; i < _activeTasks.Count; ++i)
     {
          BaseTask task = (BaseTask)_activeTasks;
          if(task.ID == ID)
               // You can't do this... static members can't be associated with an instance.
     }
}

So that's fallen through. You could go the other way and make a public method "GetID()" for every task, but then you have no way of associating a type without a reference.
TaskManager.RemoveTask(<unknown>.GetID()) // Doesn't work, no reference.

The only solution I've been able to come up with is an associative map of task IDs and a reference. The downfall of this, would be that every single task would be instantiated for the duration of the program, regardless of if it's active, paused or irrelevant to the current game state. Anyone have any other ideas? How do you handle tasks in your own engine?

Share this post


Link to post
Share on other sites
Advertisement

TaskManager.RemoveTask(VideoTask::ID); // This is OK

TaskManager :: RemoveTask(string ID)
{
for(int i = 0; i < _activeTasks.Count; ++i)
{
BaseTask task = (BaseTask)_activeTasks;
if(task.GetID() == ID)
// Okay, use instance to get static ID
}
}

class VideoTask {
string GetID() { return ID }
static string ID;
}



Why doesn't that work?

Share this post


Link to post
Share on other sites
Since the tasks are singletons, why do you need this ID and reference system?
Couldn't you just identify the tasks by pointer or reference, something like this:
Kernel::addTask( MyTask::getSingleton() );
Kernel::removeTask( MyTask::getSingleton() );


But even if you still want your ID system, it doesn't seem necessary to make the ID field static, your first example works fine if the ID field is non-static, and is initialized to the correct value when the Task is created.

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
Since the tasks are singletons
He said that they're not singletons.

Why not assign each task a unique name (at instantiation time)?
edit: lol, obviously I didn't read swiftcoder's post well enough, because that's what he suggested.

Share this post


Link to post
Share on other sites
Quote:
Original post by lucky_monkey
Quote:
Original post by swiftcoder
Since the tasks are singletons
He said that they're not singletons.


Sorry, my mistake.

[edit]
Quote:
Original post by lucky_monkey
edit: lol, obviously I didn't read swiftcoder's post well enough, because that's what he suggested.

LOL, isn't it fun how multiple posts and edits without reading the first posts can mess us up ;)[/edit]

Share this post


Link to post
Share on other sites
Well unless im not understanding what you are trying to do, why dont you make a Task class that is abstract, and have an enumeration of ID's, like

enum TaskID{ VIDEO, AUDIO, WHATEV, LOL, INPUTHANDLER};

and the base class has a protected member of the type 'TaskID", which is an enum;
then, in the construction of each derived class, you initiate the variable TaskID to a specific value, which is hardcoded in the constructor:

public VideoTask: public ParentTask
{
//constructor
VideoTask():ParentTask(VIDEO) {...}
//...
};

or sumtin

marty

Share this post


Link to post
Share on other sites
Quote:
Original post by GroZZleR
Regardless, the lack of singletons has kicked me in the ass anyways. In order to pause / resume / kill tasks, you have to be able to identify them. I have no such system and can only think of one.

Can't the kernel assign arbitrary ID value for new task in the add_task() routine, then both place it in the task (in task's non-static member variable) and return it to whoever requested addition of that task, for future refrence?


// pseudocode
unsigned int TaskManager::add_task( iTask* Task ) {

++m_task_id; // initialized to 0 or whatever in constructor
Task->set_id( m_task_id );

if( m_tasks.add( Task ) )
return m_task_id;
else
return NULL;
}

void iTask::set_id( unsigned int ID ) { m_id = ID; }

Similar to windows' hWnd thing, i guess...

Share this post


Link to post
Share on other sites
Quote:
Original post by rick_appleton
*** Source Snippet Removed ***

Why doesn't that work?


That would work, but seems a bit "sloppy" to me. More maintenance then I'd like any class to have to perform.

tolaris - your system would work fine but again, requires instances to be passed around, except this time it's an int instead of a task reference. I want to be able to arbitrarily start / stop tasks from any point in the program, regardless of where the task was created.



Share this post


Link to post
Share on other sites
Quote:
Original post by GroZZleR
tolaris - your system would work fine but again, requires instances to be passed around, except this time it's an int instead of a task reference. I want to be able to arbitrarily start / stop tasks from any point in the program, regardless of where the task was created.

I understand, but is having to provide whoever is granted the right to mess with task a reference to one beforehand... a bad thing? If the goal is to allow such thing to anyone with no preparations, no restrictions and from anywhere, then it'd be no different from how people use singletons and globals...

Share this post


Link to post
Share on other sites
If you want to be able to start or stop any task from within any other task, you could just let each task have a pointer back to the task manager.


unsigned int TaskManager::AddTask( ITask* Task )
{

// ...

Task->SetTaskManager( this );

// ...

}



Then, in VideoTask for example, you could do:

GetTaskManager()->RemoveTask( ID ); or AddTask or whatever you want.

If you are worried about TaskManager exposing too much functionality to each task, make TaskManager inherit from a small interface that only provides AddTask() and RemoveTask() and then let ITask have a pointer to that interface only.

Anyway, just an idea.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!