C# an Object-Oriented Programming
C++ is the Fastest Object-Oriented Programming
Python though the Slowest Object-Oriented Programming yet very Impressive
Java – A Cross-Platform Language
Simulation using an Object-Oriented Architecture
This project aims to design a program that simulates a burrito shop. The shop consists of servers serving customers. They execute as threads and they share resources such as the waiting area, cashier, and the ingredients for making a burrito. Besides doing the simulation, part of the objective is to make sure that no race conditions and deadlocks occur when it comes to sharing of threads. A semaphore is explicitly used to control the synchronization of the threads when using shared resources.
The solution is broken down into objects in order to visualize the operations in the burrito shop. Using the principles of object-oriented programming, different objects are created to represent some important aspects of the burrito shop case study. In this project, the identified objects are Server, Waiting Area, Outside Area, Ingredients Area, and Customer.
Upon identifying the objects, their attributes, and operations the next step is to identify whether an object is going to be a thread or a resource. Given the burrito shop case study, the Server and Customer are treated as threads while the Waiting Area, Outside Area, and Ingredients Area are shared resources.
The shared resources are protected through semaphores. A semaphore controls the concurrent update of critical attributes of the resource. Before a thread can modify a resource, they have to obtain a lock from the semaphore otherwise they have to wait for the lock to be released. A thread that holds a lock will release it for others to use after it is done doing an update on the resource.
Given the identified thread and resource objects, their relationship between them is identified. For instance, the Customer starts at the Outside Area and wait to enter only the Waiting Area if there are slots available. The Waiting Area notifies the Servers if a Customer has arrived. Servers will get the customer with the shortest order from the Waiting Area and serve them. A customer will leave the shop after all its burritos are received.
Scope and Overview
The scope of the design covers classes and objects that would make up the simulation. This includes the relationship of each object. The design also includes the data to be used in the simulation and how the simulation is going to be displayed.
The simulation’s data are randomly produced. The only data that is provided externally is the number of customers that are expected to be served. For each and every customer created, a random number between 1 and 25 burritos is going to be ordered. By default, there will only be 3 servers and 20 customers (if assuming an external number of customers is not provided).
The simulation follows an object-oriented architecture. Each object in the simulation is encapsulated with data and operations. These objects coordinate with each other to achieve a goal.
The following UML class diagram shows a summary of the simulation:
Part of the architectural design includes some software design patterns one of which is the singleton pattern. The singleton pattern is applied to objects that are for sure to appear once in the whole lifetime of the program. The Waiting Area, Outside Area, Cashier, and Ingredients Area objects are all singleton as there is one instance of each.
Another software design pattern used is the observer pattern where an object gets notified of a particular event. This pattern is heavily utilized in this project. For instance, the Server is notified when a customer enters a waiting area and a customer in the outside area is notified when a customer exits the shop.
Classes and Object Design
This would be the main driver of the simulation. It will expect to receive the number of arriving customers from an argument however if there’s none then it will use 20 customers. This class will create 3 server object threads, tells the cashier object how many customers are expected to pay, then creates the customer object threads.
Once the threads are all running, then the burrito has nothing much to do. Most of the processes are left to the threads.
There is only one cashier object in the simulation. A cashier object is a thread resource. A customer thread who has just finished being served completely will go to a cashier and pay. The cashier uses a counter to count how many customers it has processed. The counter is protected by a semaphore to avoid race conditions.
Once the cashier has accepted a number of customers, it will exit the application if the number of customers paid is the same as the number of customers expected (set by the Burrito class before the start of simulation).
The customer object is a thread. There can be many of these customer objects running at the same time. Each customer has a unique ID and variables to keep track of how many burritos it will order and how many are received. Upon creating a customer, a random number of burritos to be ordered are generated which is between 1 and 25.
Each customer executes the following steps on its lifetime:
- Generate a random number of burritos to order.
- Goes to the outside area.
- Attempts to go to the waiting area (waiting area can only accommodate 15 customers).
- If the attempt failed it will wait.
- It will stop waiting when it is signaled that a customer has left the waiting area.
- Once in the waiting area, it will wait to be signaled by a server that is available.
- Once called by a server, it will get out of the waiting area and get served for 1 up to 3 burritos.
- If there are still pending burritos to be served, it will go back to the waiting area and wait for it to be called again by an available server.
- If all burritos have been served, it goes to the cashier and pays.
- The customers that are waiting in the outside area will get notified that a customer exited the shop thus there will be available space and the next customer waiting outside will come in.
In order to make customers wait, a semaphore is used.
There is only one ingredients area object in the simulation. An ingredient contains beef, cheese, and tortillas and each of these ingredients is protected by a semaphore because they are shared by server threads. Each server will need each of these ingredients to make a burrito.
There is only one outside area object in the simulation. This area is where the arriving customer will go first. This object keeps track of all of the waiting customers who cannot go inside the waiting area because it is already full.
The list that keeps track of customers is protected by a semaphore because many customers will attempt to add themselves to the list at the same time.
The server object is a thread. There are 3 of them running at the same time. Their objective is to serve customer objects with burritos.
Each server executes the following steps on its lifetime:
- It will get the next customer from the waiting area. The waiting area is responsible for finding the next prioritized customer and gives it to the server.
- If there is no next customer then the server will wait until a signal is received that a customer entered the waiting area.
- If there is a customer then it will make 1 to 3 burritos for the customer. The customer will either go back to the waiting area if the burritos are not fully fulfilled or go to the cashier for payment.
- After which the server will do step 1 again.
In order to make servers wait, a semaphore is used.
There is only one waiting area in the simulation. The waiting area keeps track of customers that are waiting to be served. The waiting area is responsible for returning the next customer to be served. The basis for returning the next customer is done by getting the customer with the shortest number of burritos to be served.
The waiting area’s list of customers is protected by a semaphore because many customers will attempt to add themselves to the list at the same time.
All output is logged through the terminal/console window. The log includes the progress of every customer and server threads. Each customer and server is identified by a unique ID to easily keep track of them.
There are no human-computer interaction, external and/or internal interfaces.
Test with 1 Customer
This test will check if the job assigned to a customer and server are done appropriately using the right resources. Only 1 customer is created to make observation easier.
The above test shows that no deadlock is happening and the program ended gracefully. Meaning to say the resource is shared appropriately. The customer used the right resources (waiting area, outside area, and cashier). The server did its job where it provided burritos and only one server is working at a time because there’s only 1 customer to serve (other servers are waiting).
Test with 3 Customer
This test will check if the servers are serving customers in parallel.
The above test shows that 3 customers are being served in parallel. Nobody waits because there’re only 3 of them. The resources are shared appropriately.
Test with 20 Customers
This test will check that a waiting area can only hold up to 15 customers and others in the outside area will wait. The test will also show that customers in the waiting area will wait if all servers are busy with other customers.