At DW Computer Solutions we provide specialist C and C++ programming skills to
industry. We Specialize in delivering high quality solutions across a large
number of domains.
What is C
C is a general purpose computer developed at Bell Labs by Dennis Richie between
1972 and 1973.
The language itself is relatively simple and maps well to most computer hardware
on the market today.
Today C is used extensively in most operating systems. Due to its simplicity and
ubiquity, the C Application Binary Interface (ABI) for binding non-native
functionality into language like Python, Java and Lua.
The C language is now an ISO standard with a large number of vendors producing
compilers that target a large number of platforms. It consistently ranks as one
of the top 5 languages on the
What is C++
C++ was initially developed by Bjarne Stroustrup as what was essentially “C with
classes”. This brought the object oriented paradigm to the C programmer.
The last 10 years have seen major updates to the language bringing it to for
forefront of modern computer programming language design. This allows a modern
C++ programmer to use up to date designs without compromising of both control
and performance.
It is for this reason, the C++ is the language of choice for modern computer
games and embedded developers alike.
Here at DW Computers we use C++ to help you develop scalable, responsive
application.
One of my favourate additions to C++11 was std::function because it provides a very elegant solution on how to run something either at a later point in time or on a different context (like a thread).
In C++03 you would have to use something like this.
class Fn { protected: virtual ~Fn() {} virtual exec() = 0; }; You would then create a derives class of Fn on the heap and pass the pointer to the context you want to execute.
Well we are finally ready to go back the my previous post. Here I demonstrate a simple synchronous echo server. As mentioned previously. This can only allow a single client to connect to it at any given time. With coroutines we can do something like:
using namespace std::experimental::coroutines_v1; async::Task<int> runSession(std::unique_ptr<async::TcpSession> session) { printf("starting read\n"); //co_await suspends this coroutine until the read completes std::string str = co_await session->read(255); while (!str.empty()) { printf("read: %s\n", str.
Before I demonstrated a simple coroutine. Here I want to move on to a slightly more realworld usecase. You will see how to create a simple generator.
Let say I want to write a program that will generate a simple list of prime numbers. To make things simpler lets say we have the function:
bool isPrime(uint64_t num) { if (num < 2) { return false; } if (num == 2) { return true; } if (num % 2 == 0) { return false; } auto topSearch = static_cast<uint64_t>(sqrt(num)); for (auto i = 3ul; i <= topSearch; i+=2ul) { if ((num % i) == 0) { return false; } } return true; } So given a number, we can easily check if it is prime or not.
Before we examine our whole Hello World coroutine program, go through the various parts step-by-step. These include:
The coroutine Promise The coroutine Context The coroutine Future The coroutine Handle The coroutine itself The subroutine that actually uses the coroutine The entire file is included at the end of this post.
The Coroutine Future f() { co_return 42; } We instantiate our coroutine with
Future myFuture = f(); This is a simple coroutine that just returns the value 42.
In my previous post Couroutines Part 1. I explained one of why the C++ language will benefit from coroutines and why I am excited about them. Here I want to go into some of the theory behind the.
As far as a computer is concerned, memory is memory. Some is read-only and some is read-write. A CPU will fetch the content of its Program Counter (PC) and then execute it. In most cases the PC is then incremented, ready for the next instruction.
Let say we want to write an Echo Server. Simplistically we will write:
void runSession(Socket session) { while (true) { auto data = session.read(255); if (data.length() = 0) { break; } session.write(data); } session.close(); } void startServer() { while (notStopped) { Socket server; server.bind("", 7); server.listen(3); Socket session = server.accept(); runSession(std::move(session)); server.close(); } } To keep things simple I have excluded error handling from this example. Also assume a socket class that wraps the Posix C APIs.
Take the following code (in file shared.cpp):
#include <memory> #include <iostream> class A : /* public */ std::enable_shared_from_this<A> { public: explicit A(int v) : m_val( v ) {} std::shared_ptr<A> getShared() { return shared_from_this(); } void print() { std::cout << "The value is " << m_val << std::endl; } private: int m_val; }; int main() { auto a1 = std::make_shared<A>(20); auto a2 = a1->getShared(); a2->print(); return 0; } It compiles with no errors using: g++ -g -Wall -o shared shared.
The Singleton Pattern is one of the patterns listed in the famous book Gang of Four Design Patterns Book. It is probably the most common design patterns that I have seen on code that I have worked on.
It is also considered by many as an anti-pattern.
Introduction class MySingleton { public: static MySingleton* instance() { if (m_instance == nullptr) { m_instance = new MySingleton(); } return m_instance(); } <other methods> private: MySingleton(); //Needs to be private.