I'm trying to create a program in C++ where I play a beep sound, with a frequency and duration of the user's choice.
The program needs to continue running while playing the beep sound.
I figured out I should use multi-threading for this, but I don't have any experience with this.
For example, this is a simple program, but I get an error when I use _beginthread:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <process.h>
using namespace std;
int freq = 0;
int sec = 0;
int mil = 0;
void beepTone(int freqq, int mill)
{
Beep(freqq, mill);
_endthread();
}
int main()
{
cout << "Frequency?" << endl;
cin >> freq;
cout << "Duration?" << endl;
cin >> sec;
mil = 1000 * sec;
_beginthread(beepTone(freq, mil), 0, NULL);
cout << "Test Threading";
return 0;
}
Argument of type "void(*)(int freqq, int mill)" is incompatible with parameter of type "_beginthread_proc_type"
I think the point of this testing program is pretty clear.
I have code that runs, but in this code I can't choose my own frequency and duration:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <process.h>
using namespace std;
void beepTone(void *arg)
{
Beep(1000, 3000);
_endthread();
}
int main()
{
_beginthread(beepTone, 0, NULL);
cout << "Test Threading";
cin.get();
return 0;
}
This one plays 1000Hz for 3 sec while continuing the program.
Can anyone help me on how can I tell the thread which frequency and duration to play?
Your first example fails to compile because you are actually calling beepTone() and then trying to pass its void return value to the start_address parameter of _beginthread(), which will not work. You need to pass beepTone() itself to that parameter, not its return value.
Your second example is correctly passing beepTone() itself to _beginThread(), but is not passing any data to beepTone().
Now, to accomplish what you want, _beginthread() has an arglist parameter that you can use to pass user data to your thread function. That is what you need to use to send your beep values to the thread so it can then pass them to Beep().
Try something like this:
#include "stdafx.h"
#include <Windows.h>
#include <process.h>
#include <iostream>
using namespace std;
struct beepParams
{
int freq;
int mil;
};
void __cdecl beepTone(void *arg)
{
beepParams *params = static_cast<beepParams*>(arg);
Beep(params->freq, params->mil);
delete params;
_endthread();
}
int main()
{
int freq = 0, sec = 0, mil = 0;
cout << "Frequency?" << endl;
cin >> freq;
cout << "Duration?" << endl;
cin >> sec;
mil = 1000 * sec;
beepParams *params = new beepParams;
params->freq = freq;
params->mil = mil;
if (_beginthread(&beepTone, 0, params) == -1)
delete params;
cout << "Test Threading";
//...
cin.get();
return 0;
}
That being said, if you are using C++11 or later, consider using std::thread instead:
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <thread>
using namespace std;
struct beepParams
{
int freq;
int mil;
};
void beepTone(beepParams params)
{
Beep(params.freq, params.mil);
}
int main()
{
int freq = 0, sec = 0, mil = 0;
cout << "Frequency?" << endl;
cin >> freq;
cout << "Duration?" << endl;
cin >> sec;
mil = 1000 * sec;
beepParams params;
params.freq = freq;
params.mil = mil;
thread t(beepTone, params);
t.detach();
cout << "Test Threading";
//...
cin.get();
return 0;
}
Related
I'm new to thread programming. I'm trying to create an application which continually checks the Last Modification time of some file and exits the program when that time has changed.
Please find my code below:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <cerrno>
#include <unistd.h>
using namespace std;
#define NUM_THREADS 2
void *getFileCreationTime(void *path) {
const char *pt;
pt=(const char *)path;
struct stat attr;
stat("/home/utthunga/shmrp.cpp", &attr);
while(1){
char *timestamp= ctime(&attr.st_mtime);
if(timestamp)
{
cout<<"Last modified time: %s"<< ctime(&attr.st_mtime)<<endl;
cout<<"No changes has been made to the file"<<endl;
sleep(4);
}
else
{
cout<<"Last modified time: %s"<< ctime(&attr.st_mtime)<<endl;
cout<<"Time stamp has been changed"<<endl;
exit(0);
}
}
pthread_exit(NULL);
}
int main()
{
pthread_t threads[NUM_THREADS];
int i;
int rc;
for( i = 0; i < NUM_THREADS-1; i++ )
rc = pthread_create(&threads[i], NULL, getFileCreationTime, (void *)i);
pthread_exit(NULL);
return 0;
}
Can anyone please tell me what changes I have to implement in order to check the last modification time of that file continually and exit the application when that time has changed?
After you retrieve the file's modification time the first time, you need to save it so you can compare it to subsequent values retrieved afterwards.
Try something more like this instead:
void* getFileCreationTime(void *) {
const char *path = "/home/utthunga/shmrp.cpp";
struct stat attr;
if (stat(path, &attr) < 0) {
cout << "stat error" << endl;
exit(0);
}
time_t mtime = attr.st_mtime;
cout << "Last modified time: " << ctime(&mtime) << endl;
while(1) {
sleep(4);
if (stat(path, &attr) < 0) {
cout << "stat error" << endl;
exit(0);
}
if (attr.st_mtime != mtime) {
cout << "Time stamp has been changed" << endl;
exit(0);
} else {
cout << "No changes have been made to the file" << endl;
}
}
pthread_exit(NULL);
}
I think it might be something related to the way my pointers are used/initialized in my struct, but I'm not completely sure. I use 'g++ -lpthread main.cpp' to compile. The program just hangs in Linux, while executing properly in windows. The program doesn't even spit out a cout I put in the beginning of the code for debugging purposes.
#include "pthread.h"
#include "semaphore.h"
#include "time_functions.h"
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
struct vars {
char buffer[10][1000];
int put;
int take;
sem_t openSlot;
sem_t slotInactive;
sem_t newData;
ifstream readFile;
ofstream writeFile;
};
void *write(void *in) //consumer, writes data to file and deletes data from buffer
{
vars* writeVars = (vars*)in;
while (true)
{
sem_wait(&(*writeVars).newData);
sem_wait(&(*writeVars).slotInactive);
if ((*writeVars).buffer[(*writeVars).take % 10][0] != '$')
{
(*writeVars).writeFile << (*writeVars).buffer[(*writeVars).take % 10];
if ((*writeVars).readFile.eof() != true)
{
(*writeVars).writeFile << endl;
}
else
{
break;
}
}
(*writeVars).take++;
sem_post(&(*writeVars).openSlot);
sem_post(&(*writeVars).slotInactive);
}
pthread_exit(0);
return 0;
}
void *read(void *in) //producer, reads data into buffer
{
vars* readVars = (vars*)in;
char read_line[1000];
while ((*readVars).readFile.getline(read_line, 1000))
{
sem_wait(&(*readVars).openSlot);
sem_wait(&(*readVars).slotInactive);
strcpy((*readVars).buffer[(*readVars).put % 10], read_line);
(*readVars).put++;
sem_post(&(*readVars).slotInactive);
sem_post(&(*readVars).newData);
}
sem_wait(&(*readVars).openSlot);
sem_wait(&(*readVars).slotInactive);
(*readVars).buffer[(*readVars).put % 10][0] = '$';
sem_post(&(*readVars).slotInactive);
sem_post(&(*readVars).newData);
pthread_exit(0);
return 0;
}
int main(int argc, char* argv[])
{
char pause[10];
vars *varsPointer, var;
varsPointer = &var;
var.take = 0;
var.put = 0;
var.writeFile.open(argv[2], ios::out);
var.readFile.open(argv[1], ios::in);
start_timing();
sem_init(&var.openSlot, 0, 10);
sem_init(&var.slotInactive, 0, 1);
sem_init(&var.newData, 0, 0);
pthread_t read_Thread, write_Thread;
pthread_create(&read_Thread, NULL, read, varsPointer);
pthread_create(&write_Thread, NULL, write, varsPointer);
pthread_join(read_Thread, NULL);
pthread_join(write_Thread, NULL);
sem_destroy(&var.openSlot);
sem_destroy(&var.slotInactive);
sem_destroy(&var.newData);
stop_timing();
var.readFile.close();
var.writeFile.close();
//Display timer
cout << "wall clock time (ms):" << get_wall_clock_diff() * 1000 << '\n';
cout << "cpu time (ms):" << get_CPU_time_diff() * 1000 << '\n';
cout << "Type Something and Press Enter To Continue";
cin >> pause; //Just used to keep cmd promt open in Windows after program execution
return 0;
}
Having the little program below I expect the following:
>> forget_me!^C
>> next
next
>>
But it really is:
>> forget_me!^C
>> next
forget_me!next
>>
Shouldn't the default SIGINT handler clear the buffer as described here http://sunsite.ualberta.ca/Documentation/Gnu/readline-4.1/html_node/readline_40.html#SEC40 (rl_free_line_state)?
How can I achieve the desired result?
#include <cstdlib>
#include <csignal>
#include <iostream>
#include <readline/readline.h>
#include <readline/history.h>
const std::string prompt{">> "};
void new_line_handler(int i) { std::cout << "\n" << prompt; }
int main() {
struct sigaction action = {};
action.sa_handler = new_line_handler;
sigaction(SIGINT, &action, nullptr);
char *input;
while (true) {
input = readline(prompt.c_str());
if (!input)
break;
add_history(input);
std::cout << input << "\n";
free(input);
}
return 0;
}
I'm trying to make a timer which will count from the amount of time the user commands it, to zero.
Now I'm trying to add a pause faction to it, which will require to my programm to accept and read input while the timer ticks.
This is the code I have so far -
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <dos.h>
#include <windows.h>
using namespace std;
// sleep(5000);
int seconds;
int hoursLeft;
int minutesLeft;
int secondsCount=0;
void timeLeft ()
{
hoursLeft = seconds/3600;
minutesLeft = seconds/60 - hoursLeft*60;
}
void timer ()
{
if (secondsCount == 60)
{
timeLeft();
cout << "The Amount of time left is: " << hoursLeft << " hours and " << minutesLeft << " minutes left." << endl;
secondsCount=0;
}
secondsCount++;
seconds--;
Sleep(1000);
timer();
}
int main()
{
// introduction and time picking
cout << "Welcome to my Timer - Please set the amount of hours and than minutes you want the timer to run" << endl;
double requestedHours, requestedMinutes;
cin >> requestedHours;
cin >> requestedMinutes;
double requestedSeconds = requestedHours*3600 + requestedMinutes*60;
seconds = requestedSeconds;
cout << "Timer Started";
timer();
}
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
int main()
{
char buffer[16];
int flags;
int fd;
int r;
fd = 0; //stdin
flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
while (1)
{
memset(buffer, 0, sizeof(buffer));
r = read(0, buffer, sizeof(buffer)); //return the number of bytes it reads
if (r > 0) //something was read
{
printf("read: %d\n", buffer[0]);
fflush(stdin);
}
else //nothing has been read
{
puts("update timer here");
}
usleep(50000);
}
return (0);
}
using non blocking read on file descriptor can also be cool
sorry i only have this solution in C
PS: You're computer isnt suppose to work recursively infinitly, you should use a loop instead of an infinite recursion (timer() recalls itself), or your stack will overflow
I'm creating a simple chess game which uses shared memory. There are two players (Black,White) in the game and they are working in Strict Alternation principle. I get input from every player in turn-based sense and use them. My question is: I want the user to give the input like mov(a1,b2). After getting the input First: I want to validate if it is in the correct format and then I want to use the a1,b2 values in a function. Here is the part of my code:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <stdlib.h>
#include <iostream>
using namespace std;
#define SHMSZ 27
int main() {
int shmid;
key_t key;
char *shm;
string cmd;
int check =1;
key = 111;
/*
* Locate the segment.
*/
if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
perror("shmget");
return 0;
}
/*
* Now we attach the segment to our data space.
*/
if ((shm = (char*) shmat(shmid, NULL, 0)) == (char *) -1) {
perror("shmat");
return 0;
}
cout << *shm << endl;
while(check)
{
if(*shm == '*') //checks if other player finished the game
{
cout<<"End of the game. Thank you for playing." <<endl;
*shm ='*';
exit(1);
}
while(*shm == 'B')
{
cout << "Enter a move" << endl;
cin >> cmd;
if(cmd=="eog") // Finish the game
{
cout<<"End of the game. Thank you for playing." <<endl;
*shm ='*';
exit(1);
}
*shm = 'W';
}
}
return 0;
}