Resource Managers

Programs normally have complete control over the objects they create. This is fine provided these objects are not shared or sensitive resources such as threads, windows, and databases. Giving a program complete control over such a resource could be risky. What would happen, for example, if a program created a fake desktop, modified a database while another program was querying it, or created a run away thread that couldn't be interrupted?

One way to prevent such problems is to associate a resource manager to each resource class (resources are instances of resource classes). The resource manager alone is responsible for creating, manipulating, and destroying instances of that class. Resource managers provide a layer of indirection between programs and the resources they use:

Resource Manager [ROG]

Other Names

Object manager, lifecycle manager

Problem

In some situations we may need to hide from clients the details how certain resources are allocated, deallocated,  manipulated, serialized, and deserialized. In general, we may need to control client access to these objects.

Solution

A resource manager is responsible for allocating, deallocating, manipulating, tracking, serializing, and deserializing certain types of resource objects. A resource manager adds a layer of indirection between clients and resources. This layer may be used to detect illegal or risky client requests. In addition, the resource manager may provide operations that can be applied to all instances of the resource such as "save all", statistical information such as "get count", or meta-level information such as "get properties".

Static Structure

A resource manager is a singleton that maintains a table of all instances of the resource that are currently open for use:

class Manager
{
public:
   int open(); // resource factory method
   bool close(int i);
   bool serviceA(int i);
   bool serviceB(int i);
   // etc.
private:
   map<int, Resource*> open;
   bool authorized(...); // various parameters
};

If the caller is authorized, the open() function creates a new resource object, places it in the table, then returns the index to the caller. Clients must use this index number when subsequently referring to the resource. For example, here's how an authorized client invokes the serviceA() method of a previously allocated resource:

bool Manager::serviceA(int i)
{
   if (!authorized(...)) return false; // fail
   open[i]->serviceA();
   return true; // success
}

Authorization can have a variety of meanings: Does the requested resource exist? Does the client have access rights to it? Is it currently available?Is the proposed operation legal?

An operating system provides resource managers for most classes of system resources:

Window Managers

Although applications may have objects representing user interface components, these are usually just handles that wrap references to system-level bodies that directly represent user interface components (recall the handle-body idioms discussed in Chapter 4). Like files, threads, and memory, user interface components are resources that are owned and managed by the operating system. A handle representing a user interface component in an application program merely delegates requests such as move, minimize, close, etc. through the operating system's window manager to its associated body:

For example, a user interface component in an MFC application is an instance of the CWnd class (which is analogous to our UIComponent class):

class CWnd: public CCmdTarget
{
public:
   HWND m_hWnd; // "points" to a system UI component
   // etc.
};

m_hWnd is an index into a table of open windows. Most CWnd member functions simply pass this index to the operating system along with the requested operation.

A window manager is a resource manager that manages the lifecycle, appearance, size, position, and state of all user interface components on the desktop. For example, when the mouse button is clicked, the operating system might consult the window manager to determine which component was under the mouse cursor at the time of the click. Creating, destroying, hiding, moving, selecting, resizing, and repainting components can also be window manager jobs. The window manager gives a GUI its "look and feel". There are many well known window managers that are commonly used by the X Windows system: Motif window manager (mwm), OPEN LOOK window manager (olwm), and Tom's window manager (twm). X Windows programmers can even create their own window managers. The Macintosh window manager manages all open Macintosh windows. The NT object manager manages NT windows, as well as other resources such as files, processes, and threads.

View Handlers

A view handler is an application-level window manager that creates, manages, and destroys application views. The view handler also implements view commands. View commands are application-independent commands that are applied to one or more of an application's open views. For example, all MFC applications provide a Window menu containing the window commands: "New Window", "Cascade", "Tile", and "Arrange Icons". Operations such as tiling and cascading must be done by a view handler rather than views, because they require knowledge of the size and position of all open views. There is even a view handler design pattern:

View Handler [POSA]

Other Names

Window Manager, View Manager

Problem

Applications that allow multiple views often need to impose some uniformity on the appearance, attributes, and behavior of these views.

Certain meta operations such as tiling and cascading require the ability to query and manipulate all open views.

In some situations it may not make sense to have model-view-controller models be publishers.

Solution

Uniformity can be imposed by requiring all views to be derived from an abstract view base class. Introduce a component called a view handler that maintains a list of all open views. The view handler implements all view meta operations. The view handler can also notify views when they need to repaint themselves, thus models don't need to be publishers if they maintain a link to the view handler.