ofThreadChannel with custom type: no matching function for call to swap

Hi hi,

Are there any examples for using ofThreadChannel with your own class or struct?
I want to send pixels together with a time stamp. I tried doing something like this:

namespace bla {
    struct frame {
        frame(ofPixels & p, long & t): p(p), t(t) {}
        ofPixels & p;
        long & t;
    };
}
ofThreadChannel<bla::frame> channelSave;

// draw
bla::frame obj(pixels, t);
channelSave.send(obj);

But I get error: no matching function for call to 'swap' from inside ofThreadChannel. Should I implement swap in my struct? Thanks!

the problem i think it that you are storing a reference which limits a lot what you can do with an object, if you change the reference with a long it should work right away. otherwise implementing swap should work too

I tried removing the reference, and implementing swap in many different ways, but no luck.

It looks like the issue is triggered in the threaded function:

void videoGenerator::threadedFunction() {
    // GLES
    bla::frame frm;

    while(channelSave.receive(frm)) {
        addFrame(frm.p.getData(), frm.t);
    }
}

This is the massive error it triggers:

/src/openFrameworks/libs/openFrameworks/utils/ofThreadChannel.h:78:4: error: no matching function for call to 'swap'
                        std::swap(sentValue,queue.front());
                        ^~~~~~~~~
videogenerator.cpp:20:23: note: in instantiation of member function 'ofThreadChannel<bla::frame>::receive' requested here
    while(channelSave.receive(frm)) {
                      ^
/c++/6.3.1/bits/stl_bvector.h:112:3: note: candidate function not viable: no known conversion from 'bla::frame' to 'std::_Bit_reference' for 1st argument
  swap(_Bit_reference __x, _Bit_reference __y) noexcept
  ^
/c++/6.3.1/bits/stl_bvector.h:120:3: note: candidate function not viable: no known conversion from 'bla::frame' to 'std::_Bit_reference' for 1st argument
  swap(_Bit_reference __x, bool& __y) noexcept
  ^
/c++/6.3.1/bits/stl_bvector.h:128:3: note: candidate function not viable: no known conversion from 'bla::frame' to 'bool &' for 1st argument
  swap(bool& __x, _Bit_reference __y) noexcept
  ^
/c++/6.3.1/thread:231:3: note: candidate function not viable: no known conversion from 'bla::frame' to 'std::thread &' for 1st argument
  swap(thread& __x, thread& __y) noexcept
  ^
/c++/6.3.1/bits/move.h:202:5: note: candidate template ignored: could not match '_Tp [_Nm]' against 'bla::frame'
    swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
    ^
/c++/6.3.1/bits/stl_pair.h:471:5: note: candidate template ignored: could not match 'pair<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
    ^
/c++/6.3.1/bits/basic_string.h:5302:5: note: candidate template ignored: could not match 'basic_string<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'bla::frame'
    swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
    ^
/c++/6.3.1/bits/stl_vector.h:1557:5: note: candidate template ignored: could not match 'vector<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y)
    ^
/c++/6.3.1/sstream:783:5: note: candidate template ignored: could not match 'basic_stringbuf<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'bla::frame'
    swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x,
    ^
/c++/6.3.1/sstream:790:5: note: candidate template ignored: could not match 'basic_istringstream<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'bla::frame'
    swap(basic_istringstream<_CharT, _Traits, _Allocator>& __x,
    ^
/c++/6.3.1/sstream:797:5: note: candidate template ignored: could not match 'basic_ostringstream<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'bla::frame'
    swap(basic_ostringstream<_CharT, _Traits, _Allocator>& __x,
    ^
/c++/6.3.1/sstream:804:5: note: candidate template ignored: could not match 'basic_stringstream<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'bla::frame'
    swap(basic_stringstream<_CharT, _Traits, _Allocator>& __x,
    ^
/c++/6.3.1/array:275:5: note: candidate template ignored: could not match 'array<type-parameter-0-0, _Nm>' against 'bla::frame'
    swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
    ^
/c++/6.3.1/tuple:1550:5: note: candidate template ignored: could not match 'tuple<type-parameter-0-0...>' against 'bla::frame'
    swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
    ^
/c++/6.3.1/bits/unique_ptr.h:643:5: note: candidate template ignored: could not match 'unique_ptr<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(unique_ptr<_Tp, _Dp>& __x,
    ^
/c++/6.3.1/fstream:1052:5: note: candidate template ignored: could not match 'basic_filebuf<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(basic_filebuf<_CharT, _Traits>& __x,
    ^
/c++/6.3.1/fstream:1059:5: note: candidate template ignored: could not match 'basic_ifstream<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(basic_ifstream<_CharT, _Traits>& __x,
    ^
/c++/6.3.1/fstream:1066:5: note: candidate template ignored: could not match 'basic_ofstream<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(basic_ofstream<_CharT, _Traits>& __x,
    ^
/c++/6.3.1/fstream:1073:5: note: candidate template ignored: could not match 'basic_fstream<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(basic_fstream<_CharT, _Traits>& __x,
    ^
/c++/6.3.1/bits/stl_tree.h:1330:5: note: candidate template ignored: could not match '_Rb_tree<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2, type-parameter-0-3, type-parameter-0-4>' against 'bla::frame'
    swap(_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
    ^
/c++/6.3.1/bits/stl_map.h:1363:5: note: candidate template ignored: could not match 'map<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2, type-parameter-0-3>' against 'bla::frame'
    swap(map<_Key, _Tp, _Compare, _Alloc>& __x,
    ^
/c++/6.3.1/bits/stl_multimap.h:1028:5: note: candidate template ignored: could not match 'multimap<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2, type-parameter-0-3>' against 'bla::frame'
    swap(multimap<_Key, _Tp, _Compare, _Alloc>& __x,
    ^
/c++/6.3.1/bits/stl_deque.h:2274:5: note: candidate template ignored: could not match 'deque<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y)
    ^
/c++/6.3.1/bits/stl_stack.h:323:5: note: candidate template ignored: could not match 'stack<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(stack<_Tp, _Seq>& __x, stack<_Tp, _Seq>& __y)
    ^
/c++/6.3.1/bits/unordered_map.h:1754:5: note: candidate template ignored: could not match 'unordered_map<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2, type-parameter-0-3, type-parameter-0-4>' against 'bla::frame'
    swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    ^
/c++/6.3.1/bits/unordered_map.h:1761:5: note: candidate template ignored: could not match 'unordered_multimap<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2, type-parameter-0-3, type-parameter-0-4>' against 'bla::frame'
    swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
    ^
/c++/6.3.1/functional:2231:5: note: candidate template ignored: could not match 'function<type-parameter-0-0 (type-parameter-0-1...)>' against 'bla::frame'
    swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept
    ^
/c++/6.3.1/bits/shared_ptr_base.h:1302:5: note: candidate template ignored: could not match '__shared_ptr<type-parameter-0-0, _Lp>' against 'bla::frame'
    swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
    ^
/c++/6.3.1/bits/shared_ptr_base.h:1490:5: note: candidate template ignored: could not match '__weak_ptr<type-parameter-0-0, _Lp>' against 'bla::frame'
    swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
    ^
/c++/6.3.1/bits/shared_ptr.h:440:5: note: candidate template ignored: could not match 'shared_ptr<type-parameter-0-0>' against 'bla::frame'
    swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
    ^
/c++/6.3.1/bits/move.h:177:24: note: candidate template ignored: disabled by 'enable_if' [with _Tp = bla::frame]
    typename enable_if<__and_<is_move_constructible<_Tp>,
                       ^
/c++/6.3.1/bits/shared_ptr.h:533:5: note: candidate template ignored: could not match 'webla_ptr<type-parameter-0-0>' against 'bla::frame'
    swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
    ^
/c++/6.3.1/bits/stl_list.h:1918:5: note: candidate template ignored: could not match 'list<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
    ^
/c++/6.3.1/bits/std_mutex.h:363:5: note: candidate template ignored: could not match 'unique_lock<type-parameter-0-0>' against 'bla::frame'
    swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
    ^
/c++/6.3.1/bits/stl_queue.h:346:5: note: candidate template ignored: could not match 'queue<type-parameter-0-0, type-parameter-0-1>' against 'bla::frame'
    swap(queue<_Tp, _Seq>& __x, queue<_Tp, _Seq>& __y)
    ^
/c++/6.3.1/bits/stl_queue.h:618:5: note: candidate template ignored: could not match 'priority_queue<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'bla::frame'
    swap(priority_queue<_Tp, _Sequence, _Compare>& __x,
    ^
/c++/6.3.1/bits/stl_set.h:892:5: note: candidate template ignored: could not match 'set<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'bla::frame'
    swap(set<_Key, _Compare, _Alloc>& __x, set<_Key, _Compare, _Alloc>& __y)
    ^
/c++/6.3.1/bits/stl_multiset.h:875:5: note: candidate template ignored: could not match 'multiset<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'bla::frame'
    swap(multiset<_Key, _Compare, _Alloc>& __x,
    ^
1 error generated.

Does that reveal anything useful?

Just in case, this is how I added swap:

// .h
namespace bla {
    struct frame {
        public:
            frame();
            frame(ofPixels & tmpp, long tmpt): p(tmpp), t(tmpt) {}
            void swap(bla::frame & other);

            ofPixels & p;
            long t;
    };
}
namespace std {
    void swap(bla::frame & a, bla::frame & b) {
        a.swap(b);
    }
}
// .cpp
namespace bla {
    void frame::swap(bla::frame & other) {        
        std::swap(p, other.p);
        std::swap(t, other.t);
    }
}

The problem is that the definition of swap has to be available to ofTrheadChanel, otherwise it won0t work. if you declare all that before including ofMain it will solve this but fail for other reaseons.

Having references in a struct or class is not very common and limits a lot what you can do, in the few cases where it’s used is usually a reference to a member of the same class.

your example the frame() constructor can’t assign anything to the reference which would fail since you can’t just declare an uninitialized reference

Also swapping the reference to the pixels is not going to swap just the reference but the pixels themselves which is not an expensive operation but it’s probably not what you were expecting.

This works for me without defining swap and it’s much more clear what’s going on:

namespace bla {
	struct frame {
		public:
			frame(){}
			frame(ofPixels * tmpp, long tmpt): p(tmpp), t(tmpt) {}

			ofPixels * p;
			long t;
	};
}

I had tried that, but without replacing ofPixels & with ofPixels *. Now everything works nicely. Thank you! :slight_smile:

@hamoid
have you ever found a way to use ofThreadChannel with a custom object/struct ?
i too am interested in passing a pixel array to the thread and sending a different pixel array and additional data arrays back to the main ofApp.cpp thread.

thanks for any directions.

@stephanschulz I am using it with a struct, like shown above. I do not send stuff back though. Where are you stuck?

thanks for your reply.

i managed to put together a working version here:

1 Like