tags:

views:

302

answers:

6

Hi, Need help...

I have 3 classes, Manager which holds 2 pointers. One to class A another to class B . A does not know about B and vise versa.

A does some calculations and at the end it puts 3 floats into the clipboard. Next, B pulls from clipboard the 3 floats, and does it's own calculations. This loop is managed by the Manager and repeats many times (iteration after iteration).

My problem: Now class A produces a vector of floats which class B needs. This vector can have more than 1000 values and I don't want to use the clipboard to transfer it to B as it will become time consumer, even bottleneck, since this behavior repeats step by step.

Simple solution is that B will know A (set a pointer to A). Other one is to transfer a pointer to the vector via Manager But I'm looking for something different, more object oriented that won't break the existent separation between A and B

Any ideas ?

Many thanks

David

+1  A: 

Create a vector and pass it by using "pass by reference" to A and B in your iterations.

metdos
+9  A: 

It kind of sounds like you are writing a producer / consumer pair, who may communicate more easily over a (probably thread-safe) queue of floats.

In other words: the "queue" is like the vector you are currently using. Both A and B will have a reference to this queue. A runs calculations, and writes floats to the queue (possibly three at a time, if that's what you need). B checks the queue, or possibly is "signaled" by A that the queue is ready, and grabs the floats from the queue to process them.

For more info, google (or search Stack Overflow) for "producer consumer" and/or "queue", you'll probably find a lot of useful info.

(e.g. Multithreaded Work Queue in C++)

MadKeithV
Thanks.That is what I'm doing today with the 'clipboard'. The problem is now I need to transfer a vector of around 1000 values. Writing those values to clipboard and reading them back is time consuming as my application is mathematical application with many calculations and it is CPU-adjacent meaning I need to save CPU time to calculations not transferring data in/out a queue..
David
You don't need to transfer data in and out of the queue, per sé. You can use the data in the queue directly.If performance is important, have you profiled your code to see your bottlenecks? Because "CPU adjacent" to me suggests "try to work directly from the cache", and that's probably going to be pretty difficult especially if you're also working on heterogeneous, possibly multi-core hardware.
MadKeithV
Since A and B operate interleaved, the overhead of a threadsafe queue seems misplaced. Of course, it may be a valid improvement to run A and B on seperate threads (if both calculations are far more expensive than cross-thread synchronization)
MSalters
Hence the use of "probably" in my original answer - if the producer and consumer truly are easily synchronized in a single-threaded way, the queue need not be thread safe. However, since "performance" was brought up in the question, it's likely that multithreading A and B may come up quite soon.
MadKeithV
+1  A: 

B.method(A.method());

Richard
+1  A: 

The clipboard is a crazy way to transfer data between two entities.

If B implements a generic interface such as IConsumer, the manager can pass this interface to A and A can call B's method directly with the payload:

class IConsumer {
public:
   virtual void consume(const vector<float>& data) = 0;
};

class B: public IConsumer {
public:
   virtual void consume(const vector<float>& data) { ... }
   ...
};

class A {
public:
   virtual void produce(IConsumer& consumer) {
      vector<float> data;
      ...
      consumer.consume(data); 
   }
   ...
};

void Manager::tick() {
   a->produce(*b);
}
Will
A: 

The problem is solved once you realize that neither class A nor class B should be tyring to manage the shared data storage, as it's not exclusive to either. Hence, you are right in assuming that the Manager should do so.

For the best performance, don't pass a pointer to the vector to A and B. Pass a raw float* instead, as this saves a level of indirection. A compromise would be to pass a boost::array &

MSalters
A: 

As has been pointed out, you can just use an std::vector<float> as shared storage, as long as A and B do not run in different threads. The Manager could manage this storage. When A starts its work, it could request a range from that vector to store it's results. When it is done, the Manager calls B and hands it the range that has just been filled with values by A. This avoids any copying.

Space_C0wb0y