I am quite new to boost, as well as to multithreading and launching application using libraries. For my desired funcitonality, I was recommended by colleague to use boost::process library.
But the documentation to this part of boost is quite insufficient, so I could not determine which function suits my task best by documentation. I therefore started to try several functions there, but non has all the desired properties.
However there is one I cannot figure out, how to properly use. I cannot even compile it, let alone run it. And the function is boost::process::async_system. I could not find anywhere on internet some step-by-step guide on how to use this function and what individual components mean and do.
Could someone explain to me in detail the individual arguments and template arguments of the function ? Or provide a link to a detailed manual?
I like the examples here: https://theboostcpplibraries.com/boost.thread-futures-and-promises
For example, look at example 44.16, they clearly show how to use async:
#define BOOST_THREAD_PROVIDES_FUTURE
#include <boost/thread.hpp>
#include <boost/thread/future.hpp>
#include <iostream>
int accumulate()
{
int sum = 0;
for (int i = 0; i < 5; ++i)
sum += i;
return sum;
}
int main()
{
boost::future<int> f = boost::async(accumulate);
std::cout << f.get() << '\n';
}
Waiting happens at the get method, not before. You might use a non-waiting mechanism, too.
As for compiling, you need to first build boost. Building is explained in detail here: https://www.boost.org/doc/libs/1_62_0/more/getting_started/windows.html
Most parts of the library work header-only. For asio, building the binary libraries (also explained in the link) is necessary. In your project (i.e. visual studio projects, xcode project or just some make files), you need to set include and library headers of boost to use it. The link above helps with this as well.
I'm just ramping up on Boost.Process but the sample code I have working might be helpful here.
boost::process:async_system() takes 3 parameters: a boost::asio::io_context object, an exit-handler function, and the command you want to run (just like system(), and it can be either a single line or more than one arg).
After it's invoked, you use the io_context object from the calling thread to manage and monitor the async task - I use the run_one() method which will "Run the io_context object's event processing loop to execute at most one handler" but you can also use other methods to run for a duration etc.
Here's my working code:
#include <boost/process.hpp>
#include <iostream>
using namespace boost;
namespace {
// declare exit handler function
void _exitHandler(boost::system::error_code err, int rc) {
std::cout << "DEBUG async exit error code: "
<< err << " rc: " << rc <<std::endl;
}
}
int main() {
// create the io_context
asio::io_context ioctx;
// call async_system
process::async_system(ioctx, _exitHandler, "ls /usr/local/bin");
std::cout << "just called 'ls /usr/local/bin', async" << std::endl;
int breakout = 0; // safety for weirdness
do {
std::cout << " - checking to see if it stopped..." << std::endl;
if (ioctx.stopped()) {
std::cout << " * it stopped!" << std::endl;
break;
} else {
std::cout << " + calling io_context.run_one()..." << std::endl;
ioctx.run_one();
}
++breakout;
} while (breakout < 1000);
return 0;
}
The only thing my example lacks is how to use boost::asio::async_result to capture the result - the samples I've see (including here on slashdot) still don't make much sense to me, but hopefully this much is helpful.
Here's the output of the above on my system:
just called 'ls /usr/local/bin', async
- checking to see if it stopped...
+ calling io_context.run_one()...
- checking to see if it stopped...
+ calling io_context.run_one()...
VBoxAutostart easy_install pybot
VBoxBalloonCtrl easy_install-2.7 pyi-archive_viewer
((omitted - a bunch more files from the ls -l command))
DEBUG async exit error code: system:0 rc: 0
- checking to see if it stopped...
* it stopped!
Program ended with exit code: 0
Related
I couldn't come up with a better title, so feel free to give suggestions.
I tried to follow OneLoneCoder's tutorial on sound synthesizing, I'm only halfway through the first video and my code already throws an exception.
All I did was downloading his olcSoundMaker.h from his github, and copying the entry point:
#include <iostream>
#include "olcNoiseMaker.h"
double make_noise(double time)
{
return 0.5 * sin(440.0 * 2 * PI * time);
}
int main()
{
std::wcout << "Synthesizer, part 1" << std::endl;
std::vector<std::wstring> devices = olcNoiseMaker<short>::Enumerate();
for (auto d : devices)
{
std::wcout << "Found output device: " << d << std::endl;
}
olcNoiseMaker<short> sound(devices[0], 44100, 1, 8, 512);
sound.SetUserFunction(make_noise);
while (1) { ; }
return EXIT_SUCCESS;
}
In the video he runs this just fine; for me, it starts producing a sound, then after 60-80 iterations of the while (1) loop, it stops and raises this:
Unhandled exception thrown: write access violation.
std::_Atomic_address_as<long,std::_Atomic_padded<unsigned int> >(...) was 0xB314F7CC.
(from the <atomic> header file, line 1474.)
By stepping through the code with VS I didn't find out much, except that it happens at different times during every run, which may mean it has something to do with multithreading, but I'm not sure since I'm not very familiar with the topic.
I found this question which is similar, but even though it says [SOLVED] it doesn't show me the answers.
Anyone that can help to get rid of that exception?
I was using Dev C++ for coding c++ (for competitive programming, been doing it for a couple of months) but after a while I decided to try to do it on VSCode (terrible idea btw). Everything ended up working however when executing a program on the command prompt via Dev C++ it showed both the execution time and the return value of the main function like this:
Process exited after 4.962 seconds with return value 0
The problem is, when executing a c++ .exe file by normal means, these things are not shown and I don't even know where it comes from. Is there a program or a command that makes these show on the command prompt?
Edit: That comment solved my problem
"Execution time is not tracked by Windows. echo %errorlevel% prints the exit code."
A very rough example of achieving the requirement:
#include <iostream>
// to count time elapsed from beginning to end of the program
#include <chrono>
// for atexit() function
#include <cstdlib>
using namespace std::chrono;
// used globally, see the reason below of the answer
int i;
void onExit();
int main(void) {
int input;
// clock begins
steady_clock::time_point begin = steady_clock::now();
// --- SOME LONG PROGRAM ---
std::cin >> input;
// clock ends
steady_clock::time_point end = steady_clock::now();
// calculating the difference
long long diff = duration_cast<milliseconds>(end - begin).count();
// displaying the time
std::cout << "Process exited in " << diff / 1000.00 << 's' << std::endl;
// on exit of the program, this function will be executed
atexit(&onExit);
// supposing the return code is 5
i = 5;
return i;
}
// exit function to be executed before exit
void onExit() {
std::cout << "Exit code: " << i << std::endl;
}
This will output something like:
test // --- INPUT
Process exited in 4.383s
Exit code: 5
Notice that we've used the variable i globally since atexit()'s passed function must be returning void (i.e. nothing), that's the reason of not passing the i in the user-defined function onExit() and nothing else.
The definition of atexit() is as follows:
extern "C++" int atexit (void (*func)(void)) noexcept;
This is the test case
#include <boost/coroutine2/all.hpp>
#include <iostream>
#include <cassert>
int main() {
auto sum = 0;
using Coroutine_t = boost::coroutines2::coroutine<int>::push_type;
auto coro = Coroutine_t{[&](auto& yield) {
for (;;) {
auto val = yield.get();
std::cout << "Currently " << val << std::endl;
sum += val;
yield(); // jump back to starting context
}
}};
std::cout << "Transferring 1" << std::endl;
coro(1); // transfer {1} to coroutine-function
std::cout << "Transferring 2" << std::endl;
coro(2); // transfer {1} to coroutine-function
// assert(sum == 3);
}
For some reason the assert at the end fails with the value of sum being 14 I installed boost (version 1.63) context with the command
./bootstrap.sh --prefix=build --with-libraries=context
./b2 --prefix=build --with-context
I am running this on a MacOS 10.12.6. The compile command was
g++ -std=c++14 -O3 -I boost co.cpp boost/stage/lib/libboost_*.a
Where boost is the boost folder downloaded from sourceforge.
The output of the above test case strangely without the assert is this
Transferring 1
Currently 0
Transferring 2
Currently 2
Currently 2
Why is the first line printed in the coroutine Currently 0? Also why is Currently 2 is printed twice here?? The latter can be seen here as well https://wandbox.org/permlink/zEL9fGT5MrzWGgQB
For the second question it seems like after the main thread has finished, control is transferred back to the coroutine one last time. Why is that? That seems strange..
UPDATE : For the second question, it seems to be different in boost 1.65??!? https://wandbox.org/permlink/JQa9Wq1jp8kB49Up
output of your app with boost-1.65.1 is:
Transferring 1
Currently 1
Transferring 2
Currently 2
probably your problem was caused by bug that has been fixed in boost-1.63
I did a first small test with LuaBridge 1 week ago and it worked to get an int from the script.
Now I deleted this code and tried to include Lua script in my game engine but it is no longer working.
I tried to go back to a basic code with this :
#include <iostream>
#include "lua5.2/lua.hpp"
#include "LuaBridge/LuaBridge.h"
using namespace luabridge;
int main()
{
lua_State* L;
L = luaL_newstate();
if(!luaL_loadfile(L, "../../script.lua"))
std::cout << "failed loading" << std::endl;
LuaRef s = getGlobal(L, "nmbr");
int luaInt = s.cast<int>();
std::cout << luaInt << std::endl;
return 0;
}
with this script
nmbr = 30
And it gives me :
PANIC: unprotected error in cell to Lua API (bad argument #2 (number expected, got nil))
Aborted (core dumped)
It the same when I tried to get a string or a function from the script and I have no idea what I'm doing wrong in this.
Thanks for your answers :)
From the documentation of luaL_loadfileex:
As lua_load, this function only loads the chunk; it does not run it.
What that means is that the script is loaded, but it haven't been executed so there is really no variable nmbr to get. You need to run the script first for the code to work (for eample by calling lua_call).
This is shown very well in the first simple example in this LuaBridge tutorial.
luaL_loadfile ~= luaL_dofile. You load the script and get it as function on the stack but don't execute it, so the global assignment doesn't happen.
i have a synchronize function that i want to test if it ends.
i want to be able to run code for X time, and if the time ends to continue.
here what i want:
bool flag = false;
some_function_that_run_the_next_block_for_x_sec()
{
my_sync_func_that_i_want_to_test();
flag = true;
}
Assert::IsTrue(flag);
is there a simple way to do this?
SynchronizationContext
thanks.
The link you posted gives me little insight on how that class would be used (maybe Microsoft is saving up bytes on sample code to pay for Ballmer's golden parachute next year?) so pardon me for completely ignoring it.
Something like this:
auto result = async(launch::async, my_sync_func_that_i_want_to_test);
future_status status = result.wait_for(chrono::milliseconds(100));
if (status == future_status::timeout)
cout << "Timed out" << endl;
if (status == future_status::ready)
cout << "Finished on time" << endl;
Need inclusion of the <future> and <chrono> headers.
If my_sync_func_that_i_want_to_test() never finishes you'll have another problem. The future object (result) will block until the thread launched by async() finishes. There's no portable way to recover from "killed/canceled/aborted" threads, so this will probably require some platform-specific code, even if you roll out your own async_that_detaches_the_thread() (which is not hard to find, here's one example).