1

I'm currently writing a wrapper for STL stream to synchronize write calls from multiple threads. I have the following (simplified) code:

class Synchronize {
private:
    std::stringstream ss;
public:
    void write(std::string& str) {
        // locking ...
        ss << str;
        // unlocking ...
    };

    // other stuff ..
};

Synchronize& operator<<(Synchronize& o, std::string& str) {
    o.write(str);
    return o;
}

Synchronize& operator<<(Synchronize* o, std::string& str) {
    o->write(str);
    return *o;
}

Its now possible to call the write() method by using the << operator on an object of the Synchronize class, but only by using a std::string. And std::stringstream also takes a lot of other stuff like ints and floats.

Is it possible to add this functionality to my Synchronize class without a ton of own operator<< functions? Would templates help? Or should I extend some class from the iostream library?

MarcDefiant
  • 6,649
  • 6
  • 29
  • 49

2 Answers2

3

You can turn your operator overload into a friend template

Inside your class write

template<typename T>
friend Synchronize& operator<<(Synchronize& o, T const& t);

Then the definition could be

template<typename T>
Synchronize& operator<<(Synchronize& o, T const& t) {
    o.write(t);
    return o;
}

 //edit
template<typename T>
void Synchronize::write(T& t)
{
    ss << t;
}
Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
0

If I understand correctly, you want to have many readers into a single destination. The architecture you created (a wrapper on std::stream with synchronized/locked writing) is not a good solution.

Here's code that doesn't work as you would expect:

Synchronize your_stream;

void thread_function1()
{
    output << "this is a message " << "from thread_function1\n";
}
void thread_function2()
{
    output << "this is a message " << "from thread_function2\n";
}

With your code, the output may be:

this is a message this is a message from thread_function2
from thread_function1

What you need is the ability to set synchronization points wherever/whenever you want:

your_stream  out;
out << synchronize_begin << "this is " << " a test" << synchronize_end;

(this buffers everything in a synchronize_begin object (which can be dumped into a stream) and when it receives a synchronize_end object, it locks a mutex (shared with other synchronize_begin instances) and writes to out).

or:

std::ostream  out; // any std::ostream type
out << synchronized << "this is " << " a test"; // synchronized ends here

(synchronized is a buffer instance that exits scope at the end of the line; when it is written into out, it locks, then writes it's data.

utnapistim
  • 26,809
  • 3
  • 46
  • 82
  • Thank you for your answer, but this wasn't really about how to handle the synchronization. It was about the wrapper class for an STL stream and how to support more types than just `std::string` when using `operator<<` on my wrapper object. – MarcDefiant Feb 07 '13 at 14:32