Threads and Templates C++

It is Saturday morning. Last week my wife was going to have over two of his brothers and spouses but she was not feeling well so lunch was postponed for today. After breakfast I made the dough for the spinach scacciata. It is resting in a bowl. After my second and last 2-hour block I will check out the dough.

We are missing fresh mushrooms for the chicken Marsala. My wife and I will be heading out to Trader Joe’s to pick up some last minute items we need for lunch and the upcoming week.

I am back, but today is Sunday. My wife and I stopped by Trade Joe’s and pick up a few items. Back at home we decided that it would be great to have the scacciata in the oven as soon as possible. At the time it was around 11:00 AM.

I had the dough made so pulled out a large pan and with a rolling pin flatten half of the dough in a rectangular shape. Oiled the pan and laid out the dough. I then put a considerable amount of raw spinach. I do not tend to follow recipes when I cook. Besides I do not have a recipe. While I was working with the dough and spinach; my wife pitted some Italian olives. I sliced some onions and potatoes.

I spread the olives over the spinach. I then layered the onions on the spinach followed by the potatoes. I decided not to add salt or spices. I did sprinkle some Italian olive oil. Then I completely covered the spinach with ham followed by a layer of cheese. The cheese was some type of spicy variety and came in slices.

Turned on the oven and set the temperature to 400 F.

I took the remaining half of the dough and using the rolling pin made a square that would cover the baking pan. The pan has a larger lip on one side. I decided on it because is the largest we have. Using a serving fork punched the dough. It is important so the dough does not puff with the steam of the veggies. I then put an eg in a small bowl with some water and stirred it. Using a silicon brush (they clean easier) I spread the mixture over the dough.

A minute or so after I was done; it was noon and the oven reached temperature. Put in the tray for an hour. I like my scacciata with a brown color.

During the next hour my wife was chopping boneless chicken thighs. I chopped some potatoes and onions. My wife added some freshly chopped garlic. Put all the ingredients in a baking pan and added some Italian oil, salt and some mixed hot pepper mix. We have several restaurant size spice containers in our kitchen. I put in the oven the potatoes. Lunch should be done around 01:00 PM.

During the remainder time, my wife poured some peach schnapps and peach juice over a cake she baked the previous day. She wiped some cream and chopped the peaches. She covered the cake with a thick layer of wiped cream and sprinkled on top all the peaches she had chopped.

As I was taking the food out of the oven the guests arrived. I sprinkled some Italian olive oil on the scacciata so it would absorb it while it was cooling down. Lunch was ready!!!

Sorry about the space lunch took in this post. My wife and I enjoy cooking on weekends. In addition, the C++ code that follows that I wrote using my copy of Visual Studio 2019 Enterprise Edition IDE is simple and short. What I did is wrote a couple of basic functions and then experimented with it using the Template keyword.

Let’s take a look at the output from the code for the last pass that I made experimenting with changes to the main() and threadFn() functions.

main <<< entering
main <<< threadID: 10656
main <<< witing for thread(s) to complete ...
threadFc <<< entering
threadFc <<< threadID: 836
threadFn <<< Type ==>class std::vector<int,class std::allocator<int> ><== line: 30
threadFn <<< Type: class std::vector<int,class std::allocator<int> >
threadFn <<< iv.size(): 7
threadFn <<< delay: 11
threadFc <<< doing work (sleeping) ...
threadFc <<< done with work
threadFc <<< bye bye
main <<< threads completed
main <<< bye bye

The output shows the main() function displaying some output messages.

It seems that it started a threadFn() function. It displays some information about the thread and seems that it sleeps for a few seconds pretending to be busy.

The main thread is probably waiting for the thread to complete. Once the thread is done, it is detected by the main() function which displays a message and exits.

// **** include files ****
#include <iostream>
#include <thread>
#include <initializer_list>
#include <vector>


// **** namespaces ****
using namespace std;


//
// Main entry point.
//
int main    (
            )
{

    // **** welcome message ****
    cout << "main <<< entering\n";

    // **** display our thread id ****
    cout << "main <<< threadID: " << this_thread::get_id() << endl;

    // **** initialize a list of integers ****
    initializer_list<int> il = { 1,2,3,4,5 };

    // **** initialize a vector ****
    vector<int> iv = { 1,2,3,4,5,6,7 };

    // **** call the thread function ****
    //thread t1 { threadFn<int> };
    //thread t1 { threadFn<initializer_list<int>> };
    //thread t1 { threadFn, il };
    //thread t1 { threadFn<initializer_list<int>>, il};

    //thread t1{ threadFn<vector<int>>, {1, 2, 3} };
    thread t1 { threadFn<vector<int>>, iv };

    //// **** call the thread function ****
    //thread t2{ threadFn<float> };

    // **** join the thread function ****
    cout << "main <<< witing for thread(s) to complete ...\n";
    t1.join();
    //t2.join();
    cout << "main <<< threads completed\n";

    // **** bye bye message ****
    cout << "main <<< bye bye\n";

    // **** ****
    return 0;
}

The main() function started with a message, a plain thread, the join() and exit. I spent about two hours adding a second thread and then removing it. I also passed different arguments to the thread.

//
// Thread function using a template.
//
template<typename Type>
void threadFn   (
                //initializer_list<int> il
                vector<int> iv
                )

{

    // **** welcome message ****
    cout << "threadFc <<< entering\n";

    // **** display our thread id ****
    cout << "threadFc <<< threadID: " << this_thread::get_id() << endl;

    // **** display the Type ****
    cout << "threadFn <<< Type ==>" << typeid(Type).name() << "<== line: " << __LINE__ << endl;

    // **** set the delay based on the Type ****
    long delay = 0;

    // **** int ****
    if (strcmp(typeid(Type).name(), "int") == 0)
    {

        // ???? ????
        cout << "threadFn <<< Type: int\n";

        // **** set the delay ****
        delay = 3;
    }

    // **** float ****
    else if (strcmp(typeid(Type).name(), "float") == 0)
    {

        // ???? ????
        cout << "threadFn <<< Type: float\n";

        // **** set the delay ****
        delay = 5;
    }

    // **** class std::initializer_list<int> ****
    else if (strcmp(typeid(Type).name(), "class std::initializer_list<int>") == 0)
    {

        // ???? ????
        cout << "threadFn <<< Type: class std::initializer_list<int>\n";

        // **** set the delay ****
        delay = 7;

        //// **** display the size of the list ****
        //cout << "threadFn <<< il.size(): " << il.size() << endl;
    }

    // **** ****
    else if (strcmp(typeid(Type).name(), "class std::vector<int,class std::allocator<int> >") == 0)
    {

        // ???? ????
        cout << "threadFn <<< Type: class std::vector<int,class std::allocator<int> >\n";

        // **** set delay ****
        delay = 11;

        // **** display the size of the vector ***
        cout << "threadFn <<< iv.size(): " << iv.size() << endl;
    }

    // **** unknown type ****
    else
    {

        // ???? ????
        cout << "threadFn <<< Type: unknown\n";

        // **** set the delay ****
        delay = 13;
    }

    // ???? ????
    cout << "threadFn <<< delay: " << delay << endl;

    // **** pretend to do some work based on the Type ****
    cout << "threadFc <<< doing work (sleeping) ...\n";
    this_thread::sleep_for(chrono::seconds(delay));
    cout << "threadFc <<< done with work\n";

    // **** bye bye message ****
    cout << "threadFc <<< bye bye\n";
}

This function started with no template or argument. I added different templates and different arguments. Spent time experimenting with different combinations of one or two thread calls.

I see this post like a Lego or Meccano set. We have a number of pieces and we can combine them with some thought and observe if what we expect of the code is what happens. On occasions we might try something that the compiler does not like.

I used both Lego and Meccano examples because I grew up with both toys. The nice thing about them is that you could get a new set and all parts would be compatible. I liked best Meccano because things you would build would work or not. At the time when they came out, you could only build static objects with the sets. Today I believe such sets got more sophisticated but also more specific. You get a set to build a space craft and that is what you can build. With a Meccano you can build any mechanical thing you can imagine and depending on your skills and dedication you can come with your own designs. By the way you could get electric motors, cables and pulleys. A programming language and an IDE allow you to play with them in a similar fashion. Let your imagination go wild.

The main purpose of this code is to get us close to promise and await in C++. As I mentioned earlier such constructs seem to be available in most modern programming languages. They do simplify adding multi threading to applications or services with much less understanding of how they are implemented. Of course with time and experience you will like to experiment with threads in other ways that allow you to create larger and better programs and systems.

The entire code for this project can be found in my GitHub repository.

If you have comments or questions regarding this, or any other post in this blog, or if you would like for me to serve of assistance with any phase in the SDLC (Software Development Life Cycle) of a project associated with a product or service, please do not hesitate and leave me a note below. If you prefer, send me a message using the following address:  john.canessa@gmail.com. All messages will remain private.

Keep on reading and experimenting. It is the best way to learn, refresh your knowledge and enhance your developer toolset!

John

Twitter:  @john_canessa

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.