What is the default value to be given for a std::thread reference in Thread_Guard class - multithreading

I'm writing a class Thread_Guard as explained in the book Concurrency in Action at Listing 2.3 - Using RAII to wait for a thread to complete.
Below is the class
class Thread_Guard
{
thread& gThread;
public:
Thread_Guard() : gThread(NULL) {};
explicit Thread_Guard(thread& t1) : gThread(t1)
{
}
~Thread_Guard()
{
if (gThread.joinable())
gThread.join();
}
Thread_Guard(const Thread_Guard& gT1) = delete;
Thread_Guard& operator=(const Thread_Guard& gT1) = delete;
};
What is the value to be initialized for the reference to std::thread in the default constructor? I will be calling it from main like below. Where MyInt is a sample class I have written.
int main()
{
int a = 100;
MyInt customInt(a);
thread worker(customInt);
Thread_Guard(worker);
return 0;
}

The original version of thread_guard does not contain a default constructor; probably by design. It would be interesting to see the use-case motivating your question (perhaps there's an alternative?).
However, if you do want to do this, you could simply store a thread * in the class object, make the default constructor set it to nullptr, and have the destructor check this first:
class Thread_Guard
{
thread *gThread;
public:
Thread_Guard() : gThread(nullptr) {};
explicit Thread_Guard(thread& t1) : gThread(&t1)
{
}
~Thread_Guard()
{
if (gThread && gThread->joinable())
gThread->join();
}
Thread_Guard(const Thread_Guard& gT1) = delete;
Thread_Guard& operator=(const Thread_Guard& gT1) = delete;
};

Related

std::list<int> predicate call to function: Error C3867 function call missing argument list

I am using std::list's predicate to update the list based on predicate. But calling in the OnInitDialog() throws compilation error. My code is as follows:
The below is .h:
class CDlgWindow : public CDialog
{
private:
bool single_digit (const int &value);
int _days;
}
The below is .cpp:
CDlgWindow::CDlgWindow(CWnd* pParent, CString strInfo, int days) //ctor
{
_days = days;
//_strInfo = strInfo
}
bool CDlgWindow::single_digit(const int& value)
{
return (value >= _days);
}
BOOL CDlgWindow::OnInitDialog()
{
CDialog::OnInitDialog();
CenterWindow();
.
.
.
int numArr[] = {10,20,30,40};
int size = sizeof(numArr)/sizeof(numArr[0]);
std::list<int> numList (numArr, numArr+size);
numList.remove_if(single_digit); //Error C3867 here!
.
.
}
Complete error message:
Error C3867 function call missing argument list, use '&CDlgWindow::single_digit' to create a pointer to member.
I am trying to understand the functors concept. As I checked in C++11, we have lambdas for easier implementation. Please guide me to understand more on this issue. Thanks!
std::list's remove_if member needs a unary predicate (p) that operates on values (v). The expression p(v) must be valid. Which it isn't if p is a non-static class member (see repro).
There are two options:
Make the predicate (single_digit) a static class member:
class CDlgWindow : public CDialog
{
private:
static bool single_digit (const int &value);
// ...
}
Make the predicate a free function:
bool single_digit(int const& value) {
static int days_ = ...;
return (value >= days_);
}
If you go with option 1 you will have to make _days static as well, since a static member function cannot access non-static instance data. If _days is a compile-time constant, make sure to mark it const as well. That'll open up some compiler optimizations.
This is all hoping that things haven't significantly changed between C++98 and C++11. It's hard to find a C++98 compiler to verify this.

How to make a shared-state object thread safe

I am dealing with an class implementing shared-data copy semantics, so that the copy of an object will internally share the same data as the original object.
This class is essentially a wrapper around a std::shared_ptr with some convenience accessors. A stripped down version would be:
class ControlParameters {
using ControlsMap = std::map<std::string, float>;
public:
ControlParameters() : controls_(std::make_shared<ControlsMap>()) {};
ControlParameters(const ControlParameters& other) = default;
ControlParameters& operator=(const ControlParameter& other) = default;
ControlParameters(ChannelControlParameter&& other) = delete;
ControlParameters& operator=(ControlParameter&& other) = delete;
void setValue(float value, const std::string& key) const
{
auto& currentValue = (*controls_)[key];
if (currentValue != value)
currentValue = value;
};
float operator[](const std::string& key) const
{
return (*controls_)[key];
};
private:
std::shared_ptr<ControlsMap> controls_;
};
Now I realise the need to make the class thread-safe as well, to ensure atomic read/write. Note that concurrent access in this case should be intended as access from different threads and different instances sharing the same data. How can I go about it?
Note: I am aware of c++17 shared_mutex which could serve my purpose, but I cannot yet use c++17 features.

How to declare fields?

I write a GUI program in Vala. When I compile it, compiler produces this error:
The name e1 does not exist in the context of Subtract.minus
The code is:
using Gtk;
class Subtract:Window{
public Subtract(){
this.title="Subtract program";
this.destroy.connect(Gtk.main_quit);
var e1=new Entry();
var e2=new Entry();
var lbl=new Label("Result");
var btn=new Button.with_label("Subtract");
var box=new Box(Gtk.Orientation.VERTICAL,5);
box.add(e1);
box.add(e2);
box.add(lbl);
box.add(btn);
this.add(box);
btn.clicked.connect(minus);
}
public void minus(){
int a=int.parse(e1.get_text());
int b=int.parse(e2.get_text());
int result=a-b;
lbl.set_label(result.to_string());
}
public static int main(string[]args){
Gtk.init(ref args);
var win=new Subtract();
win.show_all();
Gtk.main();
return 0;
}
}
How can I make the variables accessible from the minus method.
You have to declare the variables for your widgets (at least e1, e2 and lbl) as fields:
using Gtk;
class Subtract: Window {
// Fields (sometimes also called "attributes")
private Entry e1;
private Entry e2;
private Label lbl;
private Button btn;
private Box box;
public Subtract () {
title = "Subtract program";
destroy.connect (Gtk.main_quit);
// You don't have to use "this." to access fields in Vala
// I.e. "this.e1" is equivalent to "e1" in the code below
e1 = new Entry ();
e2 = new Entry ();
lbl = new Label ("Result");
btn = new Button.with_label ("Subtract");
box = new Box (Gtk.Orientation.VERTICAL, 5);
box.add (e1);
box.add (e2);
box.add (lbl);
box.add (btn);
add (box);
btn.clicked.connect (minus);
}
public void minus () {
// The compiler happily accepts "e1" (etc.) here now
// since I have declared them as fields
int a = int.parse (e1.get_text ());
int b = int.parse (e2.get_text ());
int result = a - b;
lbl.set_label (result.to_string ());
}
public static int main (string[] args) {
Gtk.init (ref args);
var win = new Subtract ();
win.show_all ();
Gtk.main ();
return 0;
}
}
PS: The correct technical term is "scope" here. Your code had the variables at the scope of the constructor, my code as the variables as class scoped fields which makes them visible across all the methods of the class.
The Vala compiler calls it "context", which is roughly the same in this case.

How to define Task with parameters and return value in c++\cli?

i have a class in a cs file:
public class ThreadData
{
private int index;
public ThreadData(int index)
{
this.index = index;
}
public static ThreadDataOutput DoWork(ThreadDataInput input)
{
return new ThreadDataOutput();
}
}
now, i have c++ code that tries to init a new task and to us the above function:
int numOfThread = 2;
array<Task^>^ taskArr = gcnew array<Task^>(numOfThread);
for (int i = 0; i < numOfThread; i++)
{
ThreadData^ td = gcnew ThreadData(i);
ThreadDataInput^ input = gcnew ThreadDataInput(i);
Task<ThreadDataOutput^>^ task = gcnew Task<ThreadDataOutput^>(td->DoWork, input);
taskArr[i] = task;
taskArr[i]->Start();
}
Task::WaitAll(taskArr, 300 * 1000);
the following code return 2 errors at compile time:
can't take address of 'ThreadData::DoWork' unless creating delegate instance
cannot convert argument 1 from 'AmadeusWS::ThreadDataOutput ^(__clrcall *)(AmadeusWS::ThreadDataInput ^)' to 'System::Func ^
i also tried to declare a delegate like this in the cs file:
public static Func<ThreadDataInput, ThreadDataOutput> DoWork2 = delegate(ThreadDataInput taskDataInput)
{
return new ThreadDataOutput();
};
but i don't know how to call it from the c++\cli code
can anyone assist me to understand how to define cli delegate that can take parametr ?
thanks
In order to create a delegate instance in C++/CLI, you need to construct it explicitly, and specify the object that it will be called on separately from the class & method to be called.
gcnew Func<TInput, TOutput>(theObject, &TheClass::MethodToInvoke)
Note that the method to be called is specified in the C++ style.
Substituting that in to your task creation, I believe this statement will work for you:
Task<ThreadDataOutput^>^ task = gcnew Task<ThreadDataOutput^>(
gcnew Func<ThreadDataInput^, ThreadDataOutput^>(td, &ThreadData::DoWork),
input);
Edit
In the code you posted in your comment, you missed the object to invoke the delegate on.
gcnew Func<Object^, Object^>(td, &ThreadData::DoWork)
^^

haxe "should be int" error

Haxe seems to assume that certain things must be Int. In the following function,
class Main {
static function main() {
function mult_s<T,A>(s:T,x:A):A { return cast s*x; }
var bb = mult_s(1.1,2.2);
}
}
I got (with Haxe 3.01):
Main.hx:xx: characters 48-49 : mult_s.T should be Int
Main.hx:xx: characters 50-51 : mult_s.A should be Int
Can anyone please explain why T and A should be Int instead of Float?
A more puzzling example is this:
class Main {
public static function min<T:(Int,Float)>(t:T, t2:T):T { return t < t2 ? t : t2; }
static function main() {
var a = min(1.1,2.2); //compile error
var b = min(1,2); //ok
}
}
I can't see why t<t2 implies that either t or t2 is Int. But Haxe seems prefer Int: min is fine if called with Int's but fails if called with Float's. Is this reasonable?
Thanks,
min<T:(Int,Float)> means T should be both Int and Float. See the constraints section of Haxe Manual.
Given Int can be converted to Float implicitly, you can safely remove the constraint of Int. i.e. the following will works:
http://try.haxe.org/#420bC
class Test {
public static function min<T:Float>(t:T, t2:T):T { return t < t2 ? t : t2; }
static function main() {
var a = min(1.1,2.2); //ok
$type(a); //Float
trace(a); //1.1
var b = min(1,2); //ok
$type(b); //Int
trace(b); //1
}
}

Resources