As a #guru, let me pay my respects today to my #guru in the tech world, who has influenced my technical skills and mindset.
Although I have never seen them, nor do they know I exist.
But I am grateful to them - and because of them, I have at last become an engineer in the true sense.
First guru: The authors of The Gang of Four Design Pattern Book
Second Guru: Linus Torvalds for offering Linux and rather helping me come out of the vicious cycle of windows
Third Guru: The Android creator and Google for showing me the different nitty-gritty of a complicated framework that i learnt through delving into the Android framework code
Fourth Guru: A professor of a USA University by the name Doug, from whom I got insights of how to study the Android OS difficult parts of the code like the AsyncTask Framework, and he showed me the right approach of taking the OS study from an engineer’s perspective - delving into the difficult concurrent framework of the Android OS
And my all-time Guru: My family for giving me a sweet, caring, loving #home and my only son, #ridit, for becoming my best student from his early childhood. He is still driving me to burn the midnight oil in front of the laptop to explore the deep ocean of Computer science.
And I am sure, the way the whole professional world of technology is moving, very soon somebody will have to dismiss the book called
#theworldisflat - The World Is Flat
and write a new one
#theflatistheworld - The Flat Is The World
The Class Diagram
The Sequence Diagram
Runtime Behaviour
- The application creates the Context.
- The Context delegates execution to the current State.
- The State starts a Timer.
- The Timer expires.
- The Timer invokes the notification callback.
- The callback requests the Context to change its current State.
- The old state's callback instantiates the new state, triggers its operation, and then hands ownership to Mamma
- The Context delegates subsequent operations to the new State.
The source code...
#ifndef CALLBACK_H_
#define CALLBACK_H_
class Callback {
public:
virtual ~Callback() = default;
virtual void goToNextStateFromCallback() = 0;
};
#endif /* CALLBACK_H_ */
#ifndef CHICKENSTATE_H_
#define CHICKENSTATE_H_
#include <iostream>
#include "Callback.h"
#include "timer.h"
class Mamma;
class ChickenState : public Callback {
protected:
Mamma* mamma = nullptr;
Timer timer;
public:
explicit ChickenState(Mamma* inMamma) : mamma(inMamma) {
timer.setCallback(this);
}
virtual ~ChickenState() {
timer.justStop();
std::cout << "Destructor of ChickenState\n";
}
virtual void clean() {}
virtual void marinate() {}
virtual void cook() {}
virtual void serve() {}
void goToNextStateFromCallback() override {}
};
#endif /* CHICKENSTATE_H_ */
#ifndef UNCLEANEDSTATE_H_
#define UNCLEANEDSTATE_H_
#include "ChickenState.h"
#include "CleanedState.h"
#include "Mamma.h"
class UncleanedState : public ChickenState {
public:
explicit UncleanedState(Mamma* inMamma) : ChickenState(inMamma) {}
~UncleanedState() override {
std::cout << "UncleanedState destructor\n";
}
void clean() override {
std::cout << "Chicken is getting cleaned (2s)...\n";
timer.setTimeout([this]() {
timer.stop();
}, 2000);
}
void goToNextStateFromCallback() override {
std::cout << "Cleaning complete. Moving to CleanedState...\n";
auto next = std::make_shared<CleanedState>(mamma);
next->marinate(); // Trigger next step in workflow
mamma->changeChickenState(next);
}
};
#endif /* UNCLEANEDSTATE_H_ */
#ifndef CLEANEDSTATE_H_
#define CLEANEDSTATE_H_
#include "ChickenState.h"
#include "MarinatedState.h"
#include "Mamma.h"
class CleanedState : public ChickenState {
public:
explicit CleanedState(Mamma* inMamma) : ChickenState(inMamma) {}
~CleanedState() override {
std::cout << "CleanedState destructor\n";
}
void marinate() override {
std::cout << "Chicken is getting marinated (3s)...\n";
timer.setTimeout([this]() {
timer.stop();
}, 3000);
}
void goToNextStateFromCallback() override {
std::cout << "Marinating complete. Moving to MarinatedState...\n";
auto next = std::make_shared<MarinatedState>(mamma);
next->cook();
mamma->changeChickenState(next);
}
};
#endif /* CLEANEDSTATE_H_ */
#ifndef MARINATEDSTATE_H_
#define MARINATEDSTATE_H_
#include "ChickenState.h"
#include "CookedState.h"
#include "Mamma.h"
class MarinatedState : public ChickenState {
public:
explicit MarinatedState(Mamma* inMamma) : ChickenState(inMamma) {}
~MarinatedState() override {
std::cout << "MarinatedState destructor\n";
}
void cook() override {
std::cout << "Chicken is getting cooked (4s)...\n";
timer.setTimeout([this]() {
timer.stop();
}, 4000);
}
void goToNextStateFromCallback() override {
std::cout << "Cooking complete. Moving to CookedState...\n";
auto next = std::make_shared<CookedState>(mamma);
next->serve();
mamma->changeChickenState(next);
}
};
#endif /* MARINATEDSTATE_H_ */
#ifndef COOKEDSTATE_H_
#define COOKEDSTATE_H_
#include "ChickenState.h"
#include "Mamma.h"
class CookedState : public ChickenState {
public:
explicit CookedState(Mamma* inMamma) : ChickenState(inMamma) {}
~CookedState() override {
std::cout << "CookedState destructor\n";
}
void serve() override {
std::cout << "Chicken is ready! Enjoy the food.\n";
}
};
#endif /* COOKEDSTATE_H_ */
#ifndef MAMMA_H_
#define MAMMA_H_
#include <memory>
#include <iostream>
#include "ChickenState.h"
class Mamma {
private:
std::shared_ptr<ChickenState> chicken;
public:
Mamma() = default;
virtual ~Mamma();
void changeChickenState(std::shared_ptr<ChickenState> nextState);
void startPreparation();
};
#endif /* MAMMA_H_ */
#include "Mamma.h"
Mamma::~Mamma() {
std::cout << "Inside Mamma destructor\n";
}
void Mamma::changeChickenState(std::shared_ptr<ChickenState> nextState) {
chicken = std::move(nextState);
}
void Mamma::startPreparation() {
if (chicken) {
chicken->clean();
}
}
#ifndef TIMER_H_
#define TIMER_H_
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include "Callback.h"
class Timer {
private:
Callback* cb = nullptr;
std::atomic<bool> active{false};
std::mutex mtx;
std::condition_variable cv;
std::thread worker;
public:
Timer() = default;
~Timer() {
justStop();
}
void setCallback(Callback* callback) {
cb = callback;
}
template <typename Callable>
void setTimeout(Callable function, int delayMs) {
justStop();
active.store(true);
worker = std::thread([this, function, delayMs]() {
std::unique_lock<std::mutex> lock(mtx);
bool cancelled = cv.wait_for(lock, std::chrono::milliseconds(delayMs), [this]() {
return !active.load();
});
if (!cancelled && active.load()) {
function();
}
});
}
void stop() {
if (cb) {
cb->goToNextStateFromCallback();
}
}
void justStop() {
active.store(false);
cv.notify_all();
if (worker.joinable()) {
// Prevent self-join deadlock if stop() is triggered from within worker
if (worker.get_id() != std::this_thread::get_id()) {
worker.join();
} else {
worker.detach();
}
}
}
};
#endif /* TIMER_H_ */
//============================================================================
// Name : Main.cpp
// Author : Som
// Version :
// Copyright : som-itsolutions
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <thread>
#include <chrono>
#include "Mamma.h"
#include "UncleanedState.h"
int main() {
auto mamma = std::make_shared<Mamma>();
auto initialState = std::make_shared<UncleanedState>(mamma.get());
mamma->changeChickenState(initialState);
mamma->startPreparation();
// Keep main alive long enough for asynchronous timers (2s + 3s + 4s = 9s) to finish
std::this_thread::sleep_for(std::chrono::seconds(10));
return 0;
}
To compile the code above, we need to enable the -pthread option for the compiler and linker.
Enjoy...



No comments:
Post a Comment