Exchanger should provide an exchange method to let two threads at once to exchange their objects. Even tho there's no deadlock some threads got a wrong result. Debugging through I see that one of the two pointers got its value changed with some random one and I'm not able to understand why.
#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
#include <sstream>
#include <vector>
#include <random>
#include <queue>
template <typename T>
class Exchanger {
    inline static Exchanger* instance;
    inline static std::once_flag inited;
    std::mutex mutex;
    std::condition_variable to_exchange;
    T* p1 = nullptr;
    T* p2 = nullptr;
    bool ready = false;
    Exchanger(){};
    ~Exchanger(){};
public:
    static Exchanger* getInstance() {
        std::call_once(inited, []{
            instance = new Exchanger();
        });
        return instance;
    }
    T exchange(T t) {
        std::unique_lock lock(mutex);
        if (!ready) {
            p1 = &t;
            ready = true;
            to_exchange.wait(lock, [this]{return !ready;});
            return *p2;
        } else {
            p2 = &t;
            ready = false;
            to_exchange.notify_one();
            return *p1;
        }
    }
};
int* p = nullptr;
int exchange(int t) {
    p = &t;
}
int main(int argc, char **argv) {
    int x = 10;
    exchange(x);
    std::cout << *p << std::endl;
    std::vector<std::thread> traders;
    for (int i = 0; i < 4; i++) {
        traders.emplace_back([i]{
            std::this_thread::sleep_for(std::chrono::seconds(rand() % 2));
            std::stringstream msg1;
            msg1 << "thread " << std::this_thread::get_id() << " willing to trade " << i << std::endl;
            std::cout << msg1.str();
            std::stringstream msg2;
            msg2 << "thread " << std::this_thread::get_id() << " got " << Exchanger<int>::getInstance()->exchange(i) << std::endl;
            std::cout << msg2.str();
        });
    }
    for (int i = 4; i < 8; i++) {
        traders.emplace_back([i]{
            std::this_thread::sleep_for(std::chrono::seconds(rand() % 2));
            std::stringstream msg1;
            msg1 << "thread " << std::this_thread::get_id() << " willing to trade " << i << std::endl;
            std::cout << msg1.str();
            std::stringstream msg2;
            msg2 << "thread " << std::this_thread::get_id() << " got " << Exchanger<int>::getInstance()->exchange(i) << std::endl;
            std::cout << msg2.str();
        });
    }
    for (auto &t: traders) {
        if (t.joinable()) {
            t.join();
        }
    }
    return 0;
}
Also, shouldn't int exchange destroy the t<int> parameter at the end of the function? Why is the int* p still pointing to the passed value that is in fact a copy?
 
    