Take the following example
class foo {
public:
foo() {
cout << "foo has been constructed" << endl;
}
~foo() {};
void DoSomething( int i ) {
cout << "integer = " << i << endl;
}
};
int main() {
auto b = boost::bind( &foo::DoSomething,(foo*)0,_1);
b( 250 );
}
It compiles fine( this doesn't suprise me). But when I call b(), it runs fine. How is this the case? I expected, because I wasn't creating an instance of foo that calling DoSomething would case a run time problem.
Can someone explain where the instance of foo is being created? Since when I run it, I do not see the construction message printed.
foo does not get created at all.
boost-bind takes a pointer to the function. It does not care if it is C style function, a method or class function.
When you give an object instance to boost bind it just uses this object as first parameter. Since you do not require any of the instance members within DoSomething, you do not see any effect of the NULL instance.
Try and modify your example:
class foo {
public:
std:string* test_ptr;
foo() {
test_ptr=new std::string("Test");
cout << "foo has been constructed" << endl;
}
~foo() {};
void DoSomething( int i ) {
cout << "integer = " << i << endl;
cout << this->test_ptr << endl;
this->*test_ptr = "Test2"; // this is really messy with your example
}
static void DoSomething2 ( foo* sameAsThis_ptr, int i) {
this->*test_ptr = "Test3"; // compile error
// same behavior as DoSomething1
cout << "integer = " << i << endl;
cout << sameAsThis_ptr->test_ptr << endl;
sameAsThis_ptr->*test_ptr = "Test4"; // this is really messy with your example
}
};
int main() {
auto b = boost::bind( &foo::DoSomething,(foo*)0,_1);
b( 250 );
auto c = boost::bind ( &foo::DoSomething2, (foo*)NULL; _1);
c( 300 );
}
If you want to learn more you can take a closer look at "function pointers". Boost bind is just a very sophisticated way to make use of function pointers.
It wrap function pointers to an object, making functions to objects ("object functional programming")
Related
I need to create a std::queue of tasks which is executed by a thread which is only executing the latest task from the list.
The tasks are let's say for example file copy tasks. But here is the important part. I don't have to always run through the whole queue of tasks. I just want to execute the latest unexecuted task from the queue and empty the queue right after popping out the task to execute. You see this part can be tricky. I have to be careful to not clear the queue with an unexecuted task pending :-)
Following is the complete code:
#include <atomic>
#include <functional>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
using CopyTask = std::function<void(void)>;
class TaskQueue {
public:
~TaskQueue() {
StopThread();
}
void CopyTaskCompleted() {
std::unique_lock<std::mutex> que_lock(m_push_mutex);
m_trigger = true;
que_lock.unlock();
m_condition_variable.notify_one();
std::cout << " CopyTaskCompleted called " << std::endl;
}
void PushCopyTask(CopyTask task) {
std::lock_guard<std::mutex> lock(m_push_mutex);
std::cout << " PushCopyTask called " << std::endl;
if (!m_thread.joinable()) {
StartThreadLooper();
task();
return;
}
if (!m_queue.empty()) {
m_queue.push(task);
} else {
// If the queue is empty then there are no pending tasks. Simply run the task without posting it on the queue
task();
}
}
private:
std::queue<CopyTask> m_queue;
std::mutex m_queue_mutex;
std::mutex m_push_mutex;
std::condition_variable m_condition_variable;
std::thread m_thread;
std::atomic<bool> m_running {false};
bool m_trigger {false};
void StartThreadLooper() {
m_running = true;
std::cout << " Looper thread going to start " << std::endl;
m_thread = std::thread( [this] {
while (m_running) {
std::cout << " Looper thread running " << std::endl;
WaitForNotification();
if (!m_queue.empty()) {
// I want to execute the latest task from the queue here and cancel the rest of the tasks
CopyTask latest_task_to_execute = m_queue.back();
m_queue = {};
latest_task_to_execute();
}
}
});
}
void StopThread() {
std::unique_lock<std::mutex> lock(m_queue_mutex);
m_running = false;
if (m_thread.joinable()) {
try {
m_thread.join();
}
catch (const std::exception& e) {
// Log
}
}
std::cout << " Looper thread exiting " << std::endl;
}
void WaitForNotification() {
std::unique_lock<std::mutex> que_lock(m_queue_mutex);
m_condition_variable.wait(que_lock, [this] {
return m_trigger;
});
m_trigger = false;
}
};
int main() {
std::cout << " -- Beginining of program -- " << std::endl;
TaskQueue task_queue;
task_queue.PushCopyTask([&task_queue](){
std::thread t1([&] {
std::this_thread::sleep_for(std::chrono::milliseconds(70));
std::cout << " PushCopyTask number 1 fninshed executing " << std::endl;
task_queue.CopyTaskCompleted();
});
});
task_queue.PushCopyTask([&task_queue](){
std::thread t2([&] {
std::this_thread::sleep_for(std::chrono::milliseconds(70));
std::cout << " PushCopyTask number 2 fninshed executing " << std::endl;
task_queue.CopyTaskCompleted();
});
});
task_queue.PushCopyTask([&task_queue](){
std::thread t3([&] {
std::this_thread::sleep_for(std::chrono::milliseconds(70));
std::cout << " PushCopyTask number 3 fninshed executing " << std::endl;
task_queue.CopyTaskCompleted();
});
});
task_queue.PushCopyTask([&task_queue](){
std::thread t4([&] {
std::this_thread::sleep_for(std::chrono::milliseconds(70));
std::cout << " PushCopyTask number 4 fninshed executing " << std::endl;
task_queue.CopyTaskCompleted();
});
});
std::cout << " -- Ending of program -- " << std::endl;
return 0;
}
But above does not work. It seems like I am doing something wrong with the condition_variable?
How can write a tasks queue with a simple public API like above class TaskQueue has where I can pass a method to execute and it should always execute the latest method when it gets a chance.
Dev env:
Macos Big Sure with C++ clang compiler
Multiple things here:
You're using a different mutex when setting m_triggered than with the condition variable. You need to use the same one.
You're not securing the acces to m_queue via mutex in the worker thread
PushCopyTask will never push anything to the queue. It takes the mtx, sees that the queue is empty, then executes the task and returns. Simultaneous calls will block while trying to take the mtx.
If only the latest q element is supposed to be executed, why use a queue at all? I suggest using std::optional instead. Then push can just overwrite it.
I'm binding a type my_type
py::class_<my_type, std::shared_ptr<my_type>>(m, "MyType")
.def("__repr__", [](const my_type& o){return fmt::format("MyType: {}", o);});
as well as a std::vector with
py::bind_vector<std::vector<my_type>>(m, "MyTypeVector");
How can/should I declare MyTypeVector's __repr__ method here if I want its output to be a sequence of MyType.__repr__ for each object in the container?
it is actually very simple. py::bind_vector is just a wrapper around class_ so you can add methods to it just like you would add them to a normal class.
In your case you can just do
py::bind_vector<std::vector<my_type>>(m, "MyTypeVector")
.def("__repr__", [](const std::vector<my_type>& v) {// generate your string here;});
So for making the string representation, I generally define toString methods and the << operator in my c++ classes.
class BadData
{
// lots of stuff going on and removed here
virtual void
putMembers(std::ostream& out) const
{
out << "msg=" << >msg;
out << ", ";
out << "stack=" << stack;
}
virtual std::string
toString() const
{
std::ostringstream out;
out << "BadData(";
putMembers(out);
out << ")";
return out.str();
}
}
inline
std::ostream &operator<<(std::ostream& stream, const BadData &item)
{
stream << item.toString();
return stream;
}
We also have operator<< defined for stl collections
template<class T> inline
std::ostream& operator << (std::ostream& os, const std::vector<T>& v)
{
std::ostringstream out;
out << "Vector[";
if (v.size() > 0) {
for (auto ii = v.cbegin(); ii != v.cend() -1 ; ++ii) {
out << *ii << ", ";
}
out << v.back();
}
out << "]";
os << out.str();
return os;
}
So once you have all those operators defined, your __repr__ method can just look like
.def("__repr__", [](const std::vector<my_type>& v) {
std::stringstream stream;
stream << v;
return stream.str();
})
or in the case of your custom class, like
.def("__repr__", &::my_type::toString)
JesseC helped a lot, but someone pointed out a weakness in that approach: it forces either the classes to define their own operator<<, or the programmer to define it in the bindings (which is a problem if the class has already defined an operator<<, but doesn't match what he or she wants as their __repr__ output). The core library shouldn't need to be aware that it's getting binded and therefore shouldn't be forced to implement such method.
To that end, one can modify the operator<< on the std::vector to:
template<class T>
inline std::string vector_repr(const std::vector<T>& v){
std::ostringstream out;
out << "Vector[";
auto py_vector = py::cast(v);
const auto separator = ", ";
const auto* sep = "";
for( auto obj : py_vector ){
out << sep << obj.attr("__repr__")();
sep = separator;
}
out << "]";
return out.str();
}
along with the binding
py::bind_vector<MyTypeVector>(m, "MyTypeVector")
.def("__repr__", [](const MyTypeVector& v){
return vector_repr(v);
});
I am trying to handle DivideByZeroExeption in C# but the code do not catch the exeption, the Console print result of 10 / d is ∞
double d = 0;
try
{
double value = 10 / d;
Console.WriteLine(value);
}
catch (DivideByZeroException e)
{
Console.WriteLine(e.Message);
Console.WriteLine("Ignore...");
}
enter image description here
But when I changed type of d from double to int or long, this code above works normally.
int test = 0;
try
{
double value = 10 / test;
Console.WriteLine(value);
}
catch (DivideByZeroException e)
{
Console.WriteLine(e.Message);
Console.WriteLine("Ignore...");
}
Now this code will give you the error which you are expecting.
It is treating d as something else.
DivideByZeroException comes only in case of integer.
I have an application that will mirror the sales of individualities and the group that will then be presented in a panel. I currently have the code that writes the data locally on the machine, however, I need to write to the server and I can not! follows the code that I have currently attached if someone can help clarifying how to record on the server!
I've tried a few things, however, I'm lost as to how I applied the "Get remote" option, I got the data to be recorded locally, however, for the intended purpose it would have to be the option to write to the server and the application access to the object.
code:
var save2: SharedObject = SharedObject.getLocal ("data");
var b: int;
b = (save2.data.b);
trace ("trace memory value b", save2.data.b);
init2 (); // this line goes directly beneath the variables
function init2 (): void {// call once to set everything up
if (save2.data.b == null) {// checks if there is save data
trace ("No saved data yet."); // if there is any date on the computer ...
save2.data.b = 0; // ... set the savedScore to 0
} else {
trace ("Save data found."); // if we did find data ...
loadData2 (); // ... load the data
}
updateScoreText2 (); // finally, update the text field
}
function loadData2 (): void {
b = save2.data.b; // set the current score to the saved score
trace ("Data Loaded! is:", b);
}
function updateScoreText2 (): void
{
textincre11.text = b.toString () ;; // set the text property of the txtScore
trace ("Score text updated");
}
bt_incre.addEventListener (MouseEvent.CLICK, add2);
clean.addEventListener (MouseEvent.MOUSE_UP, clean4);
function somar2 (event: MouseEvent): void
{
trace ("in memory b =", b);
b ++;
trace ("Pos pos b =", b); // a = 11
textincre11.text = b.toString ();
//textincre_3.text = b.toString ();
save2.data.b = textincre11.text;
//guardar2.data.b = textincre_3.text;
save2.flush ();
trace ("trace pos somar2", save2.data.b);
}
function clean4 (e: MouseEvent): void {
b = 0;
textincre11.text = b.toString ();
//textincre_3.text = b.toString ();
save2.data.b = textincre11.text;
g // uardar2.data.b = textincre_3.text;
save2.flush ();
trace ("trace a apos equal to zero", save2.data.b);
}
bt_decrem.addEventListener (MouseEvent.CLICK, Decrease2);
function diminuir2 (event: MouseEvent): void
{
trace ("Trace in memory b =", b);
//B--;
if (b> = 1)
B--;
trace ("Decrement pos b =", b);
}
else {
return;
}
trace ("Decrement pos b =", b);
textincre11.text = b.toString ();
//textincre_3.text = b.toString ();
save2.data.b = textincre11.text;
//guardar2.data.b = textincre_3.text;
save2.flush ();
trace ("trace pos decrease2", save2.data.b);
}
The code is compiled through and run well on vs2015, but can not be compiled and report error on gcc/g++ 7.4.0, as follows:
gcc version 7.4.0 error
#include <iostream>
#include <memory>
class AA
{
public:
template<typename R, typename... Args>
R invoke(Args... args)
{
std::cout<< __FUNCTION__ << ":" << sizeof...(args) << std::endl;
return R();
}
template<typename R, typename... Args>
R call(Args... args)
{
return this->invoke<R, Args...>(args...);
}
};
template<typename T>
class BB
{
public:
BB(): lib(new T()){}
std::shared_ptr<T> lib;
};
template<typename T, typename... Args>
BB<T> make_module(Args... args)
{
BB<T> obj;
obj.lib->call<T, Args...>(args...);
return obj;
}
int main()
{
BB<AA> obj = make_module<AA>(1, 2, 3);
return 0;
}
You call member function template call on object which depends on template parameter T - BB<T> obj; you need to use template to indicate that call is member function template:
Replace
obj.lib->call<T, Args...>(args...);
by
obj.lib->template call<T, Args...>(args...);