Jump to content

Recommended Posts

Posted

I was wondering if there is any sane / simpler way to sync object data between threads other than creating a complicated messaging system like below? This is going to take a very long time to write all the possible values that might be modified:

const int THREADMESSAGE_CREATECAMERA = 1;
const int THREADMESSAGE_UPDATEENTITYORIENTATION = 2;

shared_ptr<Camera> CreateCamera(world)
{
	shared+ptr<Camera> camera = make_shared<Camera>()
	camera->world = world;

	//Add instruction to command queue
	Instruction instruction;
	instruction.id = THREADMESSAGE_CREATECAMERA;
	instruction.argument[0] = camera;
	instructions.push_back(instruction);
  
	return camera;
}
  
void Entity::SetPosition(const Vec3& position)
{
	this->position = position;
	UpdateMatrix();
  
	//Add instruction to command queue
	Instruction instruction;
	instruction.id = THREADMESSAGE_UPDATEENTITYMATRIX;
	instruction.argument[0] = this;
  	instruction.argument[1] = this->mat;
	instructions.push_back(instruction);
}

It seems like there should be a better way to do this in a more automated fashion, perhaps with templates and function / member pointers:

//Add instruction to command queue
AddInstruction( this, &Entity::color, this->color );

Some messages aren't just setting a member, some are a more complex function. This function, for example, would require additional code to send the position data to the VBOs on the graphics card:

//Add instruction to command queue
AddInstruction( this, &Surface::SetVertexData, this->positiondata->Copy() );

So what we want is some kind of Instruction object that can accept an object, a method or member pointer, and a list of arguments of any type. There's got to be something like that out there already(?)

Here is code to get the pointer to a member and a method, and to use them:

// declare pointer to member
Vec3 Entity::*member = &Entity::position;

// declare a pointer to method
void (Entity::* method) (const float, const float, const float, const bool) = &Entity::SetPosition;

auto entity = Pivot::Create();
entity->*member = Vec3(0);
(entity->*method) (1,2,3,false);

And then a templated class, something like this?:

template <class T, class Y, class P>
class Instruction
{
	shared_ptr<T> o;
  	<T>::*(something) function;  
	arguments<Y>[...] args;

	Instruction(shared_ptr<T> o, arg0<Y>, arg<P>...)
	{
		this->o = o;
		for each argument {
			arguments[n] = arg[n];
		}
	}

	void Execute()
	{
		o->*function(arg[0],arg[1],arg[2]...);
	}
}

 

Let's build cool stuff and have fun. :)

Posted

I got it working. :) The syntax is nice and simple:
 

	class Foo
	{
		int num = 1;
	public:

		void Print()
		{
			printf("%d\n",num);
		}

		void Add(int n)
		{
			num += n;
		}
	};

	std::vector<std::function<void()> > commandbuffer;

	auto f = make_shared<Foo>();

	commandbuffer.push_back(std::bind(&Foo::Add, f, 1));
	commandbuffer.push_back(std::bind(&Foo::Print, f));
	commandbuffer.push_back(std::bind(&Foo::Add, f, 36));
	commandbuffer.push_back(std::bind(&Foo::Print, f));
	commandbuffer.push_back(std::bind(&Foo::Print, f));

	for (int n = 0; n < commandbuffer.size(); ++n)
	{
		commandbuffer[n]();
	}

Output:

2
38
38

 

Let's build cool stuff and have fun. :)

Posted

I don't think there is any way to bind a member to be set to a value, without a setter function, but that's okay. This does what I need.

Let's build cool stuff and have fun. :)

Posted
On 4/8/2018 at 3:02 AM, Josh said:

I don't think there is any way to bind a member to be set to a value, without a setter function, but that's okay. This does what I need.

You should just use a lambda expression?

Color4 color(255, 0, 0, 255); // I forgot what structure LE's colors are.
AddInstruction( [this, color]() { this->color = color; } );

AddInstruction( [this]() { this->positiondata->Copy(); );

// Or whatever youre doing for the function....

It might pay off to just use lambdas and std::function.

This is the most common practice for thread "job pools".

It is likely to be more or less the exact same, they're both not pretty to read but using a lambda and it's capture list along with std::vector<std::function<void()>> to hold these functions gives you a lot more freedom in the long run.

It is not going to limit you any more as in the lambda you can edit public member variables without a setter function, for private members you would still need a setter but that's obvious. For bind you need a setter regardless of if the member is public/private.

I generally do a design similar to this: https://github.com/SaschaWillems/Vulkan/blob/master/base/threadpool.hpp

Sascha released it under the MIT license, you should use it. It is more or less exactly what you need.

Posted

This is great. Awesome stuff. I did not know you can do this with C++, it makes my life a lot easier:
 

	class Foo
	{
	public:
		int num=1;

		void Print()
		{
			printf("%d\n",num);
		}

		void Add(int n)
		{
			num += n;
		}
	};

	std::vector<std::function<void()> > commandbuffer;

	auto f = make_shared<Foo>();
	 
	commandbuffer.push_back(std::bind([f]() { f->num = 100; }));
	commandbuffer.push_back(std::bind(&Foo::Add, f, 1));
	commandbuffer.push_back(std::bind(&Foo::Print, f));
	commandbuffer.push_back(std::bind(&Foo::Add, f, 36));
	commandbuffer.push_back(std::bind(&Foo::Print, f));
	commandbuffer.push_back(std::bind(&Foo::Print, f));

	for (int n = 0; n < commandbuffer.size(); ++n)
	{
		commandbuffer[n]();
	}

 

  • Thanks 1

Let's build cool stuff and have fun. :)

Posted

Nice, I guess it makes sense they both return a function, I did not ever think that they would work together. Good to know.

If std::bind is returning a std::function<void()>, it is likely you don't need to wrap the lambda in a call to std::bind() either. Keep in mind std::bind is for class members, not lambdas.

  • Like 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...