What this code do:
Several commands executed to completion(if(current seconds == some seconds) stop).
CommandProcessor(functor) run this commands. Pointer of this class I try to throw to pthread_create.
The question:
It is possible to use class object as callable?
command.h
#ifndef COMMAND_H
#define COMMAND_H
#include <iostream>
#include "commandprocessor.h"
class CommandProcessor;
using namespace std;
class Command
{
static CommandProcessor *commandProcessor;
time_t stopSeconds;
public:
Command(int _stopSeconds);
static void setProcessor(CommandProcessor *_commandProcessor);
void execute();
};
#endif // COMMAND_H
command.cpp
#include "command.h"
CommandProcessor* Command::commandProcessor = NULL;
Command::Command(int _stopSeconds)
{
stopSeconds = _stopSeconds;
}
void Command::setProcessor(CommandProcessor *_commandProcessor)
{
commandProcessor = _commandProcessor;
}
void Command::execute()
{
time_t seconds;
time_t now = time(NULL);
seconds = localtime(&now)->tm_sec;
cout << seconds << endl;
if(seconds != stopSeconds)
commandProcessor->addCommand(this);
}
commandprocessor.h
#ifndef COMMANDPROCESSOR_H
#define COMMANDPROCESSOR_H
#include <list>
#include "command.h"
using namespace std;
class Command;
class CommandProcessor
{
list< Command* > commandsList;
public:
void addCommand(Command *_command);
void operator()();
};
#endif // COMMANDPROCESSOR_H
commandprocessor.cpp
#include "commandprocessor.h"
void CommandProcessor::addCommand(Command *_command)
{
commandsList.push_back(_command);
}
void CommandProcessor::operator()()
{
while(commandsList.size() > 0)
{
Command *command = commandsList.front();
commandsList.pop_front();
command->execute();
}
}
main.cpp
#include <iostream>
#include <pthread.h>
#include "commandprocessor.h"
#define MAX_THREADS 2
using namespace std;
int main(int argc, char **args)
{
CommandProcessor *processor = new CommandProcessor();
Command::setProcessor(processor);
processor->addCommand(new Command(53));
processor->addCommand(new Command(24));
processor->addCommand(new Command(15));
pthread_t threads[MAX_THREADS];
for(int i=0; i < MAX_THREADS; i++)
{
pthread_create(&threads[i], NULL, processor(), NULL); // error: 'processor' cannot be used as a function
}
return 0;
}
DISCLAIMER : this is the kind of thing that you really shouldn't be doing in C++, as it includes messing around with void*. It needs to be used here because of the interaction with the C API. If you can, use std::thread from C++11 or boost::thread if you're using an older compiler.
To answer your question : yes, it is perfectly fine to make a class object as a callable (as a "function") once you implement operator() for it. You already did that, but the problem is the extra code needed to implement the interface between C++ and the C API for Pthreads.
The main reason why you're getting the "processor cannot be used as a function" error here is because processor is a CommandProcessor* and, as such, needs a dereference. However, even doing (*processor)() wouldn't help you, because pthread_create is defined as follows :
int pthread_create(phread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
This means that the function to be executed must return void* and take a void*. The documentation also states that the parameter of start_routine has the value of arg originally given to the respective call to pthread_create.
However, you cannot pass a pointer to CommandProcessor::operator()() to pthread_create for a much more important reason : it is a member function. All non-static class member functions need to be called with an object so that they can refer to this inside their body.
The solution to your problem is to make a static function that will match the prototype required by pthread_create, and pass the pointer to a CommandProcessor as the arg of pthread_create. Have a look at this :
static void* processor_executor(void *arg)
{
CommandProcessor *processor = static_cast<CommandProcessor*>(arg);
(*processor)();
return NULL;
}
int main(int argc, char **argv)
{
/* ... */
for(int i=0; i < MAX_THREADS; i++)
{
pthread_create(&threads[i], NULL, processor_executor, static_cast<void*> (processor));
}
/* ... */
}
This way, operator() is executed inside the thread created by pthread_create, using the same CommandProcessor object as the one in main().
Keep in mind that accessing the same data from within many parallel threads will lead to data races. Use mutexes, semaphores, or condition variables to protect the data from parallel access.
Related
I need to add threading to my code below, whats a quick way to do so?
int main() {
ObjectType obj1;
ObjectType obj2;
printMaze(obj1, obj2);
getUserInput(obj1, obj2);
return 0;
}
void printMaze(ObjectType&obj1, ObjectType&obj2){
///
///
///
}
void getUserInput(ObjectType&obj1, ObjectType&obj2){
///
///
///
}
I want to be able to call printMaze and getUserInput in separate threads and also have them use the same variables [in essence share a variable].
just off the top of my head, this is a very quick way to implement threads on a Mac
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
//contains all the information needed
struct AllInfo{
ObjectType obj1;
ObjectType obj2;
};
int main() {
srand(time(NULL));
pthread_t printingThread;
pthread_t inputThread;
AllInfo info;
pthread_create(&printingThread, NULL, &printMaze, &info);
pthread_create(&inputThread, NULL, &getUserInput, &info);
pthread_exit(NULL);
return 0;
}
void *printMaze(void * infoArg) {
AllInfo *info;
info= ( AllInfo *)infoArg;
///
///
pthread_exit(NULL);
}
void *getUserInput(void *infoArg) {
AllInfo *info;
info= (struct AllInfo *)infoArg;;
////
////
pthread_exit(NULL);
}
you'll notice a couple of things
when passing arguments into a function that will be called in a thread,
[1] you can only pass 1 argument into that function so if you need to do more than 1 argument in the function call, you will have to bundle up the separate arguments together using a struct. and
[2]when passing arguments into a function that is being called in a thread, you will need to first accept it from the function as a object of type "void *" before typecasting it back into its original "AllInfo" objecttype.
I have the follwing code that gets core dumped error. Each C instance creates their own thread then runs. I guess there is something wrong with static function and class argument "count". When I comment out the code that prints it, no fault occurs..
#include <iostream>
#include <pthread.h>
using namespace std;
class C {
public:
int count;
C(int c_): count(c_){}
public:
void *hello(void)
{
std::cout << "Hello, world!" <<std::endl;
std::cout<<count; // bug here!!!
return 0;
}
static void *hello_helper(void *context)
{
return ((C *)context)->hello();
}
void run() {
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, NULL);
}
};
int main() {
C c(2);
c.run();
C c2(4);
c2.run();
while(true);
return 0;
}
Decided to write an answer. You were calling hello_helper with a context of NULL based on how you were creating your thread. C++ fully allows you to call member functions on null pointers, and no error occurs unless a member element is accessed.
In your case, by adding the line to print count. You are now accessing a member variable on a null pointer, which is a big no-no.
Here's an example of what you were getting away with:
#include <iostream>
class Rebel
{
public:
void speak()
{
std::cout << "I DO WHAT I WANT!" << std::endl;
}
};
int main()
{
void * bad_bad_ptr = NULL;
((Rebel*)bad_bad_ptr)->speak();
}
Output:
I DO WHAT I WANT!
By modifying your pthread_create call to pass the this pointer (i.e. pthread_create(&t, NULL, &C::hello_helper, this);, you now have a valid instance to access member variables on.
I solved the problem by passing this pointer instead off NULL while creating threads. I guess os created same thread twice int the former case ?
I'm having a problem with SDL threads so I made a little multi file code so it will be easier to show my problem
Header file
#ifndef MAINC_H_INCLUDED
#define MAINC_H_INCLUDED
#include <iostream>
#include <CONIO.H>
#include <SDL.h>
#include <SDL_thread.h>
using namespace std;
class mainc
{
private:
SDL_Thread* thread;
int threadR;
int testN=10;
public:
int threadF(void *ptr);
int OnExecute();
bool start();
};
#endif
One file
#include "mainc.h"
bool mainc::start() {
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
return false;
}
getch();
if(SDL_CreateThread(threadF, "TestThread", (void *)NULL)==NULL){
return false;
}
return true;
}
int mainc::threadF(void *ptr){
cout<<"This is a thread and here is a number: "<<testN<<endl;
return testN;
}
Second file
#include "mainc.h"
int mainc::OnExecute() {
if(!start())
{
return -1;
}
SDL_WaitThread(thread,&threadR);
return 0;
}
int main(int argc, char* argv[]) {
mainc game;
return game.OnExecute();
}
When I compile this I get this error
cannot convert 'mainc::threadF' from type 'int (mainc::)(void*)' to type 'SDL_ThreadFunction {aka int (*)(void*)}'
I dug around a bit and I found a solution but it gave me other errors I needed to make threadF static but I couldn't access any variables it gave me this error
invalid use of member 'mainc::testN' in static member function
But if I remove the variable from the function it runs fine
Now I don't know what do to because in my game I need to share variables which change
testN is neither a static nor a public property of class mainc and to do what you're trying to do, it needs to be either.
If you want to use members of class "mainc" from within another thread body, you need to pass a pointer to an object of class "mainc" to SDL_CreateThread:
// ...
SDL_CreateThread(threadF, "TestThread", this)
// ...
and then
int mainc::threadF(void *ptr)
{
mainc* myMainc = (mainc*)ptr;
myMainc->testN; // now you can use it as you need
}
Beware of the encapsulation, though (testN is actually private)
hi i have been tryng to implement a timer using posix timer libs, but i am making a mistake in the implemetation, i was using a example from the web and tryng to encapsulating in a class but, the compiler doesnt like it, basically tryng to asign the callback function int the sigev.sigev_notify_function = TIMER0_IRQHandler; but i cannot get any result.
Here goes the code:
The class definition:
#include <sys/time.h>
#include <pthread.h>
#include <signal.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
//se agrego para eliminar el siguiente warning del compilador
//warning: incompatible implicit declaration of built-in function 'memset'
#include <string.h> /* memset */
#include <unistd.h> /* close */
#define TIMEVAL_MAX 0xFFFFFFFF
#define TIMEVAL unsigned int
// The timer is incrementing every 4 us.
//#define MS_TO_TIMEVAL(ms) (ms * 250)
//#define US_TO_TIMEVAL(us) (us>>2)
// The timer is incrementing every 8 us.
#define MS_TO_TIMEVAL(ms) ((ms) * 125)
#define US_TO_TIMEVAL(us) ((us)>>3)
class Timer
{
public:
Timer();
void initTimer();
void setTimer(TIMEVAL aValue);
TIMEVAL getElapsedTime( void ) ;
void TIMER0_IRQHandler(sigval_t val);
private:
struct timeval last_sig;
timer_t timer;
};
and the function that is conflicting with the compiler:
void Timer::initTimer()
{
struct sigevent sigev;
// Take first absolute time ref.
if(gettimeofday(&last_sig,NULL)){
perror("gettimeofday()");
}
memset (&sigev, 0, sizeof (struct sigevent));
sigev.sigev_value.sival_int = 0;
sigev.sigev_notify = SIGEV_THREAD;
sigev.sigev_notify_attributes = NULL;
sigev.sigev_notify_function = &TIMER0_IRQHandler;
if( timer_create (CLOCK_REALTIME, &sigev, &timer)) {
perror("timer_create()");
}
}
*//callback function
void Timer::TIMER0_IRQHandler(sigval_t val)
{
if(gettimeofday(&last_sig,NULL)) {
perror("gettimeofday()");
}
printf("TIMER NOTIFY\n");
}
thx in advance!
To call a member function, you also need the pointer to this, which means you can't do this directly. You can, however, use a static function as a wrapper for your callback, which can extract the this pointer and call your real callback:
class Timer
{
public:
static void handler_wrapper(sigval_t val);
void handler();
};
void Timer::handler_wrapper(sigval_t val)
{
Timer *object = (Timer *)val.sival_ptr;
object->handler();
}
void Timer::handler(void)
{
// do whatever. just remember what thread context you're in
}
// in main
sigev.sigev_value.sival_ptr = (void*) this;
sigev.sigev_notify_function = &Timer::handler_wrapper;
You can use std::bind to create a function object to pass non-static member functions to be invoked at the end of timer(or timeout).
std::bind(&class_name::mem_func, obj_ptr, args_list ...);
The drawback with this is similar to static member functions, i.e. the thread does not have context of the parent object, although you might be able to run the member function stand-alone (if it doesn't use any parent object attributes). Which is pretty much the same as with static member function, which requires member attributes of the class to be static in case they are required/accessed/used by it.
Note: Pass the object reference (using std::ref) or pointer in arguments and use it in your member function.
I am having problems calling my functions from my main program.
These functions HAVE to be in my class.
How do I access them from my int main()?
#include <iostream>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <semaphore.h>
#include <synch.h>
using namespace std;
class myCountingSemaphoreUsingBinarySemaphore {
public:
void waitSemaphore(pthread_mutex_t *thread)
{
pthread_mutex_lock(*thread);// Makes value 1 (Not Available)
}
void signalSemaphore(pthread_mutex_t *thread)
{
pthread_mutex_unlock(*thread); // Makes value 0 (Available)
}
void deleteSemaphore(pthread_mutex_t *thread)
{
pthread_mutex_destroy(*thread);// Deletes
}
};
int readerCount;
int database = (rand() / 100); // Number less than 1000
void reader_writer(void);
int main(int argc, char *argv[])
{
myCountingSemaphoreUsingBinarySemaphore obj;
pthread_mutex_t mutex1;
pthread_mutex_t wrt;
pthread_create( &mutex1, NULL, reader_writer, void);
pthread_create( &wrt, NULL, reader_writer, void);
//----------------------READER------------------------//
do{
cout << "Database Before Read = " << database << endl;
obj.waitSemaphore(mutex1);//lock
readerCount++;
if (readerCount == 1)
{
obj.waitSemaphore(wrt);//lock
obj.signalSemaphore(mutex1);//unlock
//reading is preformed
obj.waitSemaphore(mutex1); // lock
readerCount--;
}
if(readerCount == 0)
{
obj.signalSemaphore(wrt);//unlock
obj.signalSemaphore(mutex1); // unlock
}
cout << "Database After Read = " << database << endl;
}while (true);
//-----------------------WRITER---------------------//
do{
cout << "Database Before Write = " << database << endl;
obj.waitSemaphore(wrt);//lock
//writing is preformed
database = database + 10;
obj.signalSemaphore(mutex1);//unlock
cout << "Database After Write = " << database << endl;
}while(true);
pthread_join( mutex1, NULL);
pthread_join( wrt, NULL);
obj.deleteSemaphore(* mutex1);
obj.deleteSemaphore(* wrt);
return 0;
}
void reader_writer () {}
Here is an error I get:
what type do they need to be? pthread_mutex_t_create? or pthread_t_create?
what is the proper type?
Functions inside a class are called methods. You need to instantiate an object of that class to be able to use it's methods:
myCountingSemaphoreUsingBinarySemaphore obj; // obj is an instance of the class
obj.waitSemaphore(&mutex1);
obj.signalSemaphore(&mutex1);
EDIT:
By the way, pthread_create and pthread_join take a pthread_t* and not a mutex!
int pthread_create(pthread_t* thread,
pthread_attr_t* attr,
void* (*start_routine)(void*),
void* arg);
You can either declare those methods as static or use an object to make the calls:
myCountingSemaphoreUsingBinarySemaphore s;
s.waitSemaphore(wrt);
You are calling class methods as just waitSemaphore without creating the object of myCountingSemaphoreUsingBinarySemaphore.
You should create the object first.
myCountingSemaphoreUsingBinarySemaphore obj;
obj.waitSemaphore(mutex1);
The two threads you create (via reader_writer()) do nothing. main() just goes into the first do loop with no way of getting out.
Also, you seem to have confused mutex, semaphores, and condition variables. The function names makes it look like you're trying to implement condition variables in your class. But you're building it as just wrappers to mutex locks.
And finally, you are calling pthread_mutex_lock() et al. on a pthread_t when those functions are supposed to be called on a pthread_mutex_t.
There probably are other errors, but these are the ones that really jump out. Basically, you need to review multi-threaded programming, both in terms of how threads are created, and how they are synchronized.
You need to create an instance of the class (an object) in order to call his member functions.
In this particular code the member functions has no reason to be instance and could be static:
class foo{
public:
static void bar(int val)
{
//do something
}
};
int main()
{
foo::bar(10);
}
karlphillip was right, you need to pass by pointer instead of reference
BTW, following line are mistake also, the pthread_create accept and pthread_t instead of pthread_mutex_t
pthread_create( &mutex1, NULL, reader_writer, void);
pthread_create( &wrt, NULL, reader_writer, void);