i'm new to c++ so I only kind of know iostream and the syntax of the language.
I am writing a program that creates an infinite amount of .txt files using fstream but i'm kind of stuck, I want it to have a menu in the program so the user could interfere with the process with the help of commands I will code in void functions("pause", "stop", etc...)
It means that the process of creating .txt files should run constantly but that the user could also write in a cin>> the keywords shown above to interfere with the process
I plan to write multiple commands so I'll surely use switch statement in the future but to show you my problem I'll only use a while loop with one command
So I've tried things like that:
void stop()
{
return 0;
}
int main()
{
string command= "";
int i=1;
if (command!="stop")
{
while (i<=2)
{
CreateNewFile();
cin >> command;
}
} else
{
stop();
}
}
But the problem with this kind of loop is that it asks the user to write something everytime in order to reset the loop and it is this thing in particular that I want to avoid...
I want to keep the loop running as long as my user wants it to
I'm sure that the answer is really simple but i've not found any help by asking google so i'll tr to ask you guys.
Thank you in advance to those who will take the time to asnwer me
My advise, Adam, is to change your problem description so you ask user how many files they want to create, and then run the loop that many times:
for(;;) {
unsigned n;
cout << "How many files do you want to create (0 to stop)? ";
cin >> n;
if(!n) break;
for(unsigned i = 0; i < n; i++) {
CreateNewFile();
}
}
I had something on this line wherein the thread that's doing the actual work continues and only processes commands if the user wants to.
#include <iostream>
#include <string>
#include <thread>
#include <stack>
#include <chrono>
#include <mutex>
int main() {
std::stack<std::string> commandQueue;
std::mutex m;
int i = 0;
std::thread worker([&]() {
bool suspend = false;
while(true) {
{
const std::lock_guard<std::mutex> lock(m);
if(!commandQueue.empty()){
std::string command = commandQueue.top();
commandQueue.pop();
if(command == "continue"){
suspend = false;
//process continue
} else if (command == "pause"){
suspend = true;
//process other commands....
} else if(command == "stop") {
//process stop
return; //exit thread
}
}
}
//Commands processed, continue as usual
if(!suspend) {//Process only if not paused
using namespace std::chrono_literals;
//Continue creating files or whatever it is that needs to be done continuously
std::this_thread::sleep_for(500ms);
i++;
//std::cout<<"Value of i is "<<i<<'\n';
//CreatFileName();
}
}
});
std::string command;
do {
std::cout<<"Enter commands to interact\n";
std::cin>>command;
{
const std::lock_guard<std::mutex> lock(m);
commandQueue.push(command);
}
}while(command != "stop");
worker.join();
std::cout<<"After execution, value of i is "<<i<<'\n';
}
Of course, the output of this specific example is a bit ugly because it is printing to the console from 2 different threads but the commands like stop, pause, continue are processed fine since there's only one thread (the main thread) that reads in the commands but since this is just to demonstrate how one can possibly achieve what you intend to, I didn't spend up too much time on the output aesthetics.
So after a while this is basically the simplest solution:
#include <iostream>
#include <thread>
#include <string>
static bool finished = false;
void createFile() {
while (!finished) {
//Your code
}
}
int main() {
std::string answer;
std::thread question(createFile);
std::cin >> answer;
if (answer == "stop") {
finished = true;
}
question.join();
return 0;
}
Here we create a thread which will keep running until they type stop. I ran the code and it was working I made it print out 1 until I wrote stop.
Related
I wrote a program that writes random numbers to one file in the first thread, and another thread reads them from there and writes to another file those that are prime numbers. The third thread is needed to stop/start the work. I read that I/O threads are thread-safe. Since writing to a single shared resource is thread-safe, what could be the problem?
Output: always correct record in numbers.log, sometimes no record in numbers_prime.log when there are prime numbers, sometimes they are all written.
#include <iostream>
#include <fstream>
#include <thread>
#include <mutex>
#include <vector>
#include <condition_variable>
#include <future>
#include <random>
#include <chrono>
#include <string>
using namespace std::chrono_literals;
std::atomic_int ITER_NUMBERS = 30;
std::atomic_bool _var = false;
bool ret() { return _var; }
std::atomic_bool _var_log = false;
bool ret_log() { return _var_log; }
std::condition_variable cv;
std::condition_variable cv_log;
std::mutex mtx;
std::mutex mt;
std::atomic<int> count{0};
std::atomic<bool> _FL = 1;
int MIN = 100;
int MAX = 200;
bool is_empty(std::ifstream& pFile) // function that checks if the file is empty
{
return pFile.peek() == std::ifstream::traits_type::eof();
}
bool isPrime(int n) // function that checks if the number is prime
{
if (n <= 1)
return false;
for (int i = 2; i <= sqrt(n); i++)
if (n % i == 0)
return false;
return true;
}
void Log(int min, int max) { // function that generates random numbers and writes them to a file numbers.log
std::string str;
std::ofstream log;
std::random_device seed;
std::mt19937 gen{seed()};
std::uniform_int_distribution dist{min, max};
log.open("numbers.log", std::ios_base::trunc);
for (int i = 0; i < ITER_NUMBERS; ++i, ++count) {
std::unique_lock<std::mutex> ulm(mtx);
cv.wait(ulm,ret);
str = std::to_string(dist(gen)) + '\n';
log.write(str.c_str(), str.length());
log.flush();
_var_log = true;
cv_log.notify_one();
//_var_log = false;
//std::this_thread::sleep_for(std::chrono::microseconds(500000));
}
log.close();
_var_log = true;
cv_log.notify_one();
_FL = 0;
}
void printCheck() { // Checking function to start/stop printing
std::cout << "Log to file? [y/n]\n";
while (_FL) {
char input;
std::cin >> input;
std::cin.clear();
if (input == 'y') {
_var = true;
cv.notify_one();
}
if (input == 'n') {
_var = false;
}
}
}
void primeLog() { // a function that reads files from numbers.log and writes prime numbers to numbers_prime.log
std::unique_lock ul(mt);
int number = 0;
std::ifstream in("numbers.log");
std::ofstream out("numbers_prime.log", std::ios_base::trunc);
if (is_empty(in)) {
cv_log.wait(ul, ret_log);
}
int oldCount{};
for (int i = 0; i < ITER_NUMBERS; ++i) {
if (oldCount == count && count != ITER_NUMBERS) { // check if primeLog is faster than Log. If it is faster, then we wait to continue
cv_log.wait(ul, ret_log);
_var_log = false;
}
if (!in.eof()) {
in >> number;
if (isPrime(number)) {
out << number;
out << "\n";
}
oldCount = count;
}
}
}
int main() {
std::thread t1(printCheck);
std::thread t2(Log, MIN, MAX);
std::thread t3(primeLog);
t1.join();
t2.join();
t3.join();
return 0;
}
This has nothing to do with the I/O stream thread safety. The shown code's logic is broken.
The shown code seems to follow a design pattern of breaking up a single logical algorithm into multiple pieces, and scattering them far and wide. This makes it more difficult to understand what it's doing. So let's rewrite a little bit of it, to make the logic more clear. In primeLog let's do this instead:
cv_log.wait(ul, []{ return _var_log; });
_var_log = false;
It's now more clear that this waits for _var_log to be set, before proceeding on its merry way. Once it is it gets immediately reset.
The code that follows reads exactly one number from the file, before looping back here. So, primeLog's main loop will always handle exactly one number, on each iteration of the loop.
The problem now is very easy to see, once we head over to the other side, and do the same clarification:
std::unique_lock<std::mutex> ulm(mtx);
cv.wait(ulm,[]){ return _var; });
// Code that generates one number and writes it to the file
_var_log = true;
cv_log.notify_one();
Once _var is set to true, it remains true. This loops starts running full blast, iterating continuously. On each iteration of the loop it blindly sets _var_log to true and signals the other thread's condition variable.
C++ execution threads are completely independent of each other unless they are explicitly synchronize in some way.
Nothing is preventing this loop from running full blast, getting through its entire number range, before the other execution thread wakes up and decides to read the first number from the file. It'll do that, then go back and wait for its condition variable to be signaled again, for the next number. Its hopes and dreams of the 2nd number will be left unsatisfied.
On each iteration of the generating thread's loop the condition variable, for the other execution thread, gets signaled.
Condition variables are not semaphores. If nothing is waiting on a condition variable when it's signaled -- too bad. When some execution thread decides to wait on a condition variable, it may or may not be immediately woken up.
One of these two execution thread relies on it receiving a condition variable notification for every iteration of its loop.
The logic in the other execution thread fails to implement this guarantee. This may not be the only flaw, there might be others, subject to further analysis, this was just the most apparent logical flaw.
Thanks to those who wrote about read-behind-write, now I know more. But that was not the problem. The main problem was that if it was a new file, when calling pFile.peek() in the is_empty function, we permanently set the file flag to eofbit. Thus, until the end of the program in.rdstate() == std::ios_base::eofbit.
Fix: reset the flag state.
if (is_empty(in)) {
cv_log.wait(ul, ret_log);
}
in.clear(); // reset state
There was also a problem with the peculiarity of reading/writing one file from different threads, though it was not the cause of my program error, but it led to another one.
Because if when I run the program again primeLog() opens std::ifstream in("numbers.log") for reading faster than log.open("numbers.log", std::ios_base::trunc), then in will save old data into its buffer faster than log.open will erase them with the std::ios_base::trunc flag. Hence we will read and write to numbers_prime.log the old data.
This is a home assignment.
Have to print a string(given as input) in small chunks(Size given as input) by multiple threads one at a time in order 1,2,3,1,2,3,1,2(number of threads is given as input).
A thread does this printing function on creation and I want it to redo it after all the other threads. I face two problems:
1. Threads don't print in fixed order(mine gave 1,3,2,4 see output)
2. Threads need to re print till the entire string is exhausted.
This is what I tried...
#include<iostream>
#include<mutex>
#include<thread>
#include<string>
#include<vector>
#include<condition_variable>
#include<chrono>
using namespace std;
class circularPrint{
public:
int pos;
string message;
int nCharsPerPrint;
mutex mu;
condition_variable cv;
circularPrint(){
pos=0;
}
void shared_print(int threadID){
unique_lock<mutex> locker(mu);
if(pos+nCharsPerPrint<message.size())
cout<<"Thread"<<threadID<<" : "<<message.substr(pos,nCharsPerPrint)<<endl;
else if(pos<message.size())
cout<<"Thread"<<threadID<<" : "<<message.substr(pos)<<endl;
pos+=nCharsPerPrint;
}
};
void f(circularPrint &obj,int threadID){
obj.shared_print(threadID);
}
int main(){
circularPrint obj;
cout<<"\nMessage : ";
cin>>obj.message;
cout<<"\nChars : ";
cin>>obj.nCharsPerPrint;
int nthreads;
cout<<"\nThreads : ";
cin>>nthreads;
vector<thread> threads;
for(int count=1;count<=nthreads;++count)
{
threads.push_back(thread(f,ref(obj),count));
}
for(int count=0;count<nthreads;++count)
{
if(threads[count].joinable())
threads[count].join();
}
return 0;
}
Why would you want to multithread a method that can only be executed once at a time?
Anyway, something like this below? Be aware that the take and print use different locks and that there is a chance the output does not show in the expected order (hence, the why question above).
#include <iostream>
#include <mutex>
#include <thread>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class circularPrint
{
public:
int pos;
string message;
int nCharsPerPrint;
mutex takeLock;
mutex printLock;
circularPrint() {
pos = 0;
}
string take(int count) {
lock_guard<mutex> locker(takeLock);
count = std::min(count, (int)message.size() - pos);
string substring = message.substr(pos, count);
pos += count;
return substring;
}
void print(int threadID, string& message) {
lock_guard<mutex> locker(printLock);
cout << "Thread" << threadID << " : " << message << endl;
}
void loop(int threadID) {
string message;
while((message = take(nCharsPerPrint)).size() > 0) {
print(threadID, message);
}
}
};
void f(circularPrint &obj, int threadID)
{
obj.loop(threadID);
}
int main()
{
circularPrint obj;
//cout << "\nMessage : ";
//cin >> obj.message;
//cout << "\nChars : ";
//cin >> obj.nCharsPerPrint;
int nthreads;
//cout << "\nThreads : ";
//cin >> nthreads;
nthreads = 4;
obj.message = "123456789012345";
obj.nCharsPerPrint = 2;
vector<thread> threads;
for (int count = 1; count <= nthreads; ++count)
threads.push_back(thread(f, ref(obj), count));
for (int count = 0; count < nthreads; ++count) {
if (threads[count].joinable())
threads[count].join();
}
return 0;
}
Currently each thread exits after printing one message - but you need more messages than threads, so each thread will need to do more than one message.
How about putting an infinite loop around your current locked section, and breaking out when there are no characters left to print?
(You may then find that the first thread does all the work; you can hack that by putting a zero-length sleep outside the locked section, or by making all the threads wait for some single signal to start, or just live with it.)
EDIT: Hadn't properly realised that you wanted to assign work to specific threads (which is normally a really bad idea). But if each thread knows its ID, and how many there are, it can figure out which characters it is supposed to print. Then all it has to do is wait till all the preceding characters have been printed (which it can tell using pos), do its work, then repeat until it has no work left to do and exit.
The only tricky bit is waiting for the preceding work to finish. You can do that with a busy wait (bad), a busy wait with a sleep in it (also bad), or a condition variable (better).
You need inter thread synchronization, each thread doing a loop "print, send a message to next one, wait for a message (from the last thread)".
You can use semaphores, events, messages or something similar.
Something as:
#include <string>
#include <iostream>
#include <condition_variable>
#include <thread>
#include <unistd.h>
using namespace std;
// Parameters passed to a thread.
struct ThreadParameters {
string message; // to print.
volatile bool *exit; // set when the thread should exit.
condition_variable* input; // condition to wait before printing.
condition_variable* output; // condition to set after printing.
};
class CircularPrint {
public:
CircularPrint(int nb_threads) {
nb_threads_ = nb_threads;
condition_variables_ = new condition_variable[nb_threads];
thread_parameters_ = new ThreadParameters[nb_threads];
threads_ = new thread*[nb_threads];
exit_ = false;
for (int i = 0; i < nb_threads; ++i) {
thread_parameters_[i].message = to_string(i + 1);
thread_parameters_[i].exit = &exit_;
// Wait 'your' condition
thread_parameters_[i].input = &condition_variables_[i];
// Then set next one (of first one if you are the last).
thread_parameters_[i].output =
&condition_variables_[(i + 1) % nb_threads];
threads_[i] = new thread(Thread, &thread_parameters_[i]);
}
// Start the dance, free the first thread.
condition_variables_[0].notify_all();
}
~CircularPrint() {
// Ask threads to exit.
exit_ = true;
// Wait for all threads to end.
for (int i = 0; i < nb_threads_; ++i) {
threads_[i]->join();
delete threads_[i];
}
delete[] condition_variables_;
delete[] thread_parameters_;
delete[] threads_;
}
static void Thread(ThreadParameters* params) {
for (;;) {
if (*params->exit) {
return;
}
{
// Wait the mutex. We don't really care, by condition variables
// need a mutex.
// Though the mutex will be useful for the real assignement.
unique_lock<mutex> lock(mutex_);
// Wait for the input condition variable (frees the mutex before waiting).
params->input->wait(lock);
}
cout << params->message << endl;
// Free next thread.
params->output->notify_all();
}
}
private:
int nb_threads_;
condition_variable* condition_variables_;
ThreadParameters* thread_parameters_;
thread** threads_;
bool exit_;
static mutex mutex_;
};
mutex CircularPrint::mutex_;
int main() {
CircularPrint printer(10);
sleep(3);
return 0;
}
using vector<shared_ptr<...>> would be more elegant than just arrays, though this works:
g++ -std=c++11 -o test test.cc -pthread -Wl,--no-as-needed
./test
Lets say I want to take an input from user and perform a search in a text file for that input. The search will be performed for every character user inputs. There will be a loop performing search and there will be another loop to check if new character is input by the user. Second loop will restart the first loop if new char is given by the user.
Please just explain how to perform above with c++. I think threads need to be created.
Below variables will be used to maintain common values:
static var`
bool change;
while(!change)
{
change=false
<<do something, like search in file>>
}
Other loop will be like below:
while(1)
{
if(user enters another char)
{
var=new value input by the user;
change=true;
}
else change=false;
}
Thanks!
Something like this? Now I wrote this on ideone and their threads didn't work for me so I wasn't able to test it but yeah.. Something close to this should work. Probably a bad example. A thread pool would be best.
#include <iostream>
#include <thread>
#include <atomic>
#include <queue>
#include <mutex>
#include <chrono>
std::mutex lock;
std::atomic<bool> stop(false);
std::queue<std::function<void()>> jobs;
void One()
{
while(!stop)
{
if (!jobs.empty())
{
if (lock.try_lock())
{
std::function<void()> job = jobs.front();
jobs.pop();
lock.unlock();
job();
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void Two()
{
std::string var;
while(true)
{
if (std::cin>> var)
{
std::lock_guard<std::mutex> glock(lock);
jobs.push([] {std::cout<<"Task added to the queue..\n";});
}
else
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
int main()
{
std::thread T(One);
Two();
stop = true;
T.join();
return 0;
}
Create two threads: one for reading user-input, and another for performing the search.
Use a binary-semaphore in order to synchronize between the two threads in a Consumer-Producer manner, i.e., one thread acquires the semaphore and the other thread releases it:
static BinarySemaphore binSem;
static int inputCharacter = 0;
static void ReadUserInput();
static void PerformSearch();
void Run()
{
BinarySemaphore_Init(&binSem,0);
CreateThread(ReadUserInput,LOWER_PRIORITY);
CreateThread(PerformSearch,HIGHER_PRIORITY);
}
static void ReadUserInput()
{
while (inputCharacter != '\n')
{
inputCharacter = getc(stdin);
BinarySemaphore_Set(&binSem);
}
}
static void PerformSearch()
{
while (inputCharacter != '\n')
{
BinarySemaphore_Get(&binSem,WAIT_FOREVER);
// <<do something, like search in file>>
}
}
Please note that you need to create the thread which performs the search, with priority higher than that of the thread which reads user-input (as in the code above).
I'm quite new to boost::threads, I read the documentation and but i'm having some trouble applying it in practice, perhaps you can help? First of all, I have taken the time to write a self contained code listing that demonstrates 2 types of behavior that I cannot yet understand...
The program allows the user to issue 3 different commands,
task [name]
info
quit
The purpose is that task will launch some work on a new thread, but then return back to the command prompt while the work is carried out. The user can give the info command to find out which tasks have completed and which have not.
Im using a dual core Win7 machine and Visual Studio 2008 Express.
Problem 1>
Issuing the command, task p1 p2 p3, starts 3 tasks running. This can be checked by issuing info. After a few seconds the work is complete, however for some reason the completed flag is not always set true on 1 or 2 of the tasks.
Problem 2>
Quiting the program then produces the following message:
Windows has triggered a breakpoint in example.exe. This may be due to a corruption of the heap, which indicates a bug in example.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while example.exe has focus.
The output window may have more diagnostic information.
Hopefully you can reproduce this behavior and help.
Thanks in advance.
Alex.
//WARNING: THIS CODE DOES NOT BEHAVE EXACTLY AS INTENDED
#include <iostream>
#include <string>
#include <sstream>
#include <boost/thread.hpp>
using namespace std;
class task {
public:
string mname;
bool completed;
void start()
{
int a = 0;
for (int i=0 ; i<10000; i++)
{
for (int j=0 ; j<100000; j++)
{
a= i*2;
}
}
this->completed = true;
}
task(string name)
{
mname = name;
completed = false;
}
};
class taskManager{
public:
boost::thread_group threads;
void startTask( string name )
{
//add new task to vector list
mtasks.push_back( task(name) );
// execute start() on a new thread
threads.create_thread( boost::bind( &task::start, &mtasks.back()) );
}
int tasksTotal()
{
return mtasks.size();
}
string taskInfo(int i)
{
string compstr("Not Completed");
if ( mtasks[i].completed == true )
{
compstr = "Completed";
}
return mtasks[i].mname + " " + compstr;
}
private:
vector<task> mtasks;
};
int main(int argc, char* argv[])
{
string cmd, temp;
stringstream os;
bool quit = false;
taskManager mm;
cout << "PROMPT>";
while (quit == false)
{
//Wait for a valid command from user
getline(cin,cmd);
// Reset stringstream and assign new cmd string
os.clear();
os << "";
os << cmd;
//parse input string
while (os >> temp)
{
if ( temp.compare("task") == 0 )
{
while (os >> temp) { mm.startTask( temp ); }
}
if ( temp.compare("info") == 0 )
{
// Returns a list of all completed and not completed tasks
for (int i = 0; i<mm.tasksTotal(); i++)
{
cout << mm.taskInfo(i).c_str() << endl;
}
}
if ( temp.compare("quit") == 0 ){ quit = true; }
}
cout << "PROMPT>";
}
mm.threads.join_all();
return 0;
};
There is a problem with your code in the taskManager::startTask method:
mtasks.push_back( task(name) );
// execute start() on a new thread
threads.create_thread( boost::bind( &task::start, &mtasks.back())
The problem here is that on pushing back a new task, your vector might have to reallocate some space and such invalidate the references to your old vector elements, such the following calls to taskinfo will reference to the wrong elements. As you delete the old elements your heap will somehow get corrupted.
An easy fix would be to reserve some space for the vector in the constructor of your taskManager class, however you should probably change the design of your task/taskmanager model instead. Another way would be to use a std::deque, as that one won't reallocate memory.
Background: I'm trying to figure out how to implement continuations/coroutines/generators (whatever the following is called) by posing this toy problem. The environment is C++11 on gcc 4.6 and linux 3.0 x86_64. Non-portable is fine but using an external library (boost.coroutine, COROUTINE, etc) is not allowed. I think longjmp(3) and/or makecontext(2) and friends may help but not sure.
Description:
The following toy parser is supposed to parse sequences of as and bs of equal length. ie
((a+)(b+))+
such that the length of the second bracketed production equals the third.
When it finds a production (eg aaabbb) it outputs the number of as it finds (eg 3).
Code:
#include <stdlib.h>
#include <iostream>
using namespace std;
const char* s;
void yield()
{
// TODO: no data, return from produce
abort();
}
void advance()
{
s++;
if (*s == 0)
yield();
}
void consume()
{
while (true)
{
int i = 0;
while (*s == 'a')
{
i++;
advance();
}
cout << i << " ";
while (i-- > 0)
{
if (*s != 'b')
abort();
advance();
}
}
}
void produce(const char* s_)
{
s = s_;
// TODO: data available, continue into consume()
consume();
}
int main()
{
produce("aaab");
produce("bba");
produce("baa");
produce("aabbb");
produce("b");
// should print: 3 1 4
return 0;
}
Problem:
As you can see the state of the consume call stack must be saved when yield is called and then produce returns. When produce is called again, consume must be restarted by returning from yield. The challenge would be to modify the way produce calls consume, and implement yield so they function as intended.
(Obviously reimplementing consume so that it saves and rebuilds its state defeats the purpose of the exercise.)
I think what needs to be done is something like the example on the bottom of the makecontext man page: http://www.kernel.org/doc/man-pages/online/pages/man3/makecontext.3.html, but its not clear how to translate it onto this problem. (and I need sleep)
Solution:
(Thanks to Chris Dodd for design)
#include <stdlib.h>
#include <iostream>
#include <ucontext.h>
using namespace std;
const char* s;
ucontext_t main_context, consume_context;
void yield()
{
swapcontext(&consume_context, &main_context);
}
void advance()
{
s++;
if (*s == 0)
yield();
}
void consume()
{
while (true)
{
int i = 0;
while (*s == 'a')
{
i++;
advance();
}
cout << i << " ";
while (i-- > 0)
{
advance();
}
}
}
void produce(const char* s_)
{
s = s_;
swapcontext(&main_context, &consume_context);
}
int main()
{
char consume_stack[4096];
getcontext(&consume_context);
consume_context.uc_stack.ss_sp = consume_stack;
consume_context.uc_stack.ss_size = sizeof(consume_stack);
makecontext(&consume_context, consume, 0);
produce("aaab");
produce("bba");
produce("baa");
produce("aabbb");
produce("b");
// should print: 3 1 4
return 0;
}
Its fairly straight-forward to use makecontext/swapcontext for this -- you use makecontext to create a new coroutine context and swapcontext to swap between them. In you case, you need one additional coroutine to run the consume infinite loop, and you run main and produce in the main context.
So main should call getcontext+makecontext to create a new context that will run the consume loop:
getcontext(&consume_ctxt);
// set up stack in consume_context
makecontext(&consume_ctxt, consume, 0);
and then produce will switch to it instead of calling consume directly:
void produce(const char* s_)
{
s = s_;
swapcontext(&main_ctxt, &consume_ctxt);
}
and finally yield just calls swapcontext(&consume_ctxt, &main_ctxt); to switch back to the main context (which will continue in produce and immediately return).
Note that since consume is an infinite loop, you don't need to worry too much about what happens when it returns (so the link will never be used)