Csnd:: vs std::

Hello again dear Csounders!

When developing a csound opcode using c++ framework it seems that std::thread isn’t that welcome :frowning: . Why is that?

Are there any other limitations that one should have in mind? E.g. regarding memory management (smart pointers, containers…) or something else like only c++11 should be used and so on…

std::thread should work Ok. I’m not sure about containers, I don’t think I’ve ever used a smart pointer in any of my cpof opcodes. Note there is a deinit() function that you can register that will be called when the opcode is finished. You can tidy memory there if you need to.

Hi @rory! And thanks (again) for jumping in :beers:

when I want to use std::thread there is a conflict with a macro named _CR I can make workaround like this

#ifdef _CR
#undef _CR
#include <thread>
#define _CR (0x0020)
#else
#include <thread>
#endif

but I don’t know if this is safe?

And if I make something like

void print_hello() {
    std::cout << "Hello from a worker thread!" << std::endl;
}

struct StdThreadTest : csnd::Plugin<0, 0> {
    std::thread t;
    int init() {
        t = std::thread(print_hello);
        t.join();
        return OK;
    }
};

#include <modload.h>

void csnd::on_load(Csound *csound) {
    csnd::plugin<StdThreadTest>(csound, "std_threading", "", "", csnd::thread::i);
}

opcode doesn’t run in csound (I get: “Unexpected untyped word std_threading when expecting a variable Parsing failed due to invalid input!”). If I don’t create and run a thread opcode runs fine.

Am I doing something wrong here?

And pthread seems to work fine:

void* print_hello(void* arg) {
    std::cout << "Hello from worker thread!" << std::endl;
    pthread_exit(NULL);
}

struct PthrdThreadTest : csnd::Plugin<0, 0> {
    pthread_t simple_thread;

    int init() {
        int rc = pthread_create(&simple_thread, NULL, print_hello, NULL);
        std::cout << "Hello from the main thread!" << std::endl;
        return OK;
    }
};

#include <modload.h>

void csnd::on_load(Csound *csound) {
    csnd::plugin<PthrdThreadTest>(csound, "pthrd_threading", "", "", csnd::thread::i);
}

That’s Ok, there is a cinflict betwee the “_CR” definition in the standard C++ library and in Csound, although it’s only an issue on Windows from what I can tell. If you undef _CR before including any Csound headers it should be fine. With regards to the std::thread issue, I just checked an opcode I wrote that uses it, and this is how my include section looks:

#undef _CR
#include <plugin.h>
#include

I don’t think you need to worry about redefining _CR as it will be redefined elsewhere. I guess if pthread works ago, you might as well use that? But you have to link to the pthread library which is a little annoying.

1 Like

Hi @rory !

There are few sentences in Victor’s paper to this topic (that I’ve overseen :woozy_face: ) :


4.3. Memory Allocation

Csound provides its own managed heap for dynamic memory allocation. .... 
It is not advisable for developers to employ any other memory allocation methods. ....

Well that couldn’t be clearer. So no std::vectors but csnd::AuxMem and csnd::Vector


6. Multithreading Support

The Csound API includes an interface for multithreading, which is implemented via pthreads [28] on POSIX systems, or other native threading libraries in non-POSIX platforms.
To allow opcodes an object-oriented access to this C interface, CPOF provides the Thread pure virtual class. ....

So no std::thread but csnd::Thread (or pthread)…

" I guess if pthread works ago, you might as well use that?" → Yes, it’s just that std::jthread is much more convenient but csnd::Thread and pthread will suffice :beers: