top of page

Giving Concurrency a Home

Architecture Evolves with Technology

Software architecture is built around separation of responsibility. Applications separate persistence from business logic, presentation from communication, configuration from implementation, and logging from application behavior. As systems become more capable, responsibilities naturally become concentrated into well-defined architectural components.


Concurrency followed a different path. For many years, it was rarely considered an architectural concern. A background thread might be introduced to keep the user interface responsive, or a small pool of workers might process long-running tasks. These decisions were viewed as implementation details rather than part of the application's overall structure. That reflected the hardware of the time.


As processors became faster, applications often became faster without significant architectural change. Sequential execution remained the natural model, while concurrency was reserved for the relatively small number of operations that benefited from running in the background.


Modern processors evolved differently. Instead of relying primarily on increasing clock frequencies, processors gained additional cores and hardware threads, allowing many independent operations to execute simultaneously. Increasingly, performance came from parallel execution rather than from making a single sequence of instructions run faster. As hardware evolved, software evolved with it. Concurrency was no longer simply a technique for improving responsiveness. It became part of how applications performed their everyday work.


Applications Execute Work


Applications do not execute threads: they execute work. Threads are simply one of the mechanisms available to execute that work.


Within Photo Supreme, these are everyday operations. Importing images, generating thumbnails, reading metadata, updating the catalog, detecting faces, synchronizing versions, and many other background activities all represent different categories of work.


Although they may participate in the same user action, they often have very different execution characteristics. Some operations naturally execute one at a time because ordering influences the result. Others can safely process many independent tasks in parallel. Some operations support cancellation, while others are expected to run to completion once they begin. These characteristics belong to the work itself rather than to the threads executing it.


From Work to Workflows


Many operations consist of more than a single category of work. Importing a collection of images is a good example. Depending on the selected import profile, files may first be copied from a memory card, then renamed, registered in the catalog, enriched with metadata, analysed, thumbnails generated, and optionally removed from the source device once the import has completed successfully.


Each stage performs a different kind of work. Some stages are naturally sequential because each decision depends on the previous one. Others benefit from processing many images simultaneously. Some stages may not participate at all because the selected import profile skips them entirely. What remains constant is the workflow.


The work progresses through a sequence of well-defined stages until the operation is complete. Within Photo Supreme, this workflow is represented by a thread session. A thread session coordinates the overall workflow, while each individual stage delegates its work to a component responsible for executing that specific category of work.


Thinking Like a Factory


A useful way to think about this architecture is as a factory. The thread session is the production order moving through the factory. The import profile is the production plan. It determines which departments participate in the production process and which can be skipped.


Each department specializes in one kind of work. One department copies files. Another assigns filenames. Another registers images in the catalog. Another extracts metadata. Another generates thumbnails. Each department has its own procedures, its own capacity, and its own way of handling the work that arrives.


The workers perform the work. The department defines the process.


Some departments may have a single worker because every task must be completed in order. Others may have many workers because every item can be processed independently. The number of workers is determined by the nature of the work, not by the workflow itself.


When a department has completed its work, the production order moves to the next department. Eventually it leaves the factory as a finished product.


The Architecture in Practice


Photo Supreme follows this same architectural model. A thread session represents the workflow. It knows which stages participate in the operation and when work moves from one stage to the next. Each stage is implemented by a thread service. A thread service owns one category of work together with its execution policy: accepting work items, managing worker threads, applying concurrency limits, interpreting cancellation, coordinating progress, and handling shutdown and cleanup.


The worker threads themselves are temporary executors. They perform the work assigned to them, but they do not own the process. Just as workers in a factory may change without affecting the production line, worker threads may come and go while the execution model remains unchanged. The responsibility for executing work belongs to the thread service, while the responsibility for coordinating the workflow belongs to the thread session.


bottom of page