10
\$\begingroup\$

This is an emulator I am currently re-writing for my Operating Systems course. It is a simple emulator that is supposed to represent hardware, OS, etc. It is strictly for learning purposes and I want to propose my solution to the teacher as a method of modern C++ (since his solution is more "C with classes").

However, before I do that, I would like to make sure I don't embarrass myself with bad code.

Right now I'm debating on my association between hardware and OS. They are currently written like so:

// Hardware.h
class OS;
class Hardware : boost::noncopyable
{
    friend class OS;

private:
    Hardware(OS *os);

    void load_job(boost::shared_ptr<Job> job);
    void run_job();

private:
    void execute_instruction(Instruction const& instruction);
    void handle_interrupt(Instruction const& trap);

private:
    enum { NumberOfRegisters     = 32 };
    enum { InstructionMemorySize = 1024 };
    enum { DataMemorySize        = 1024 };

    OS                            *m_pOS;

    std::vector<int>               m_Registers;
    boost::ptr_vector<Instruction> m_InstructionMemory;
    std::vector<int>               m_DataMemory;

    boost::optional<int>           m_Counter;
};


// OS.h
class Hardware;
class OS : boost::noncopyable
{
    friend class Hardware;

public:
    OS();

    // Load jobs
    void boot();
    // Execute jobs
    void run();

private:
    // "Interrupts"
    void trap_halt(int status);
    void trap_getw(int& receiver);
    void trap_putw(int value);
    void trap_dump();

    void time_elapsed();

private:
    void get_next_job();

private:
    boost::scoped_ptr<Hardware> m_pHardware;
    boost::scoped_ptr<Parser>   m_pParser;

    boost::ptr_deque<Job>       m_Jobs;
    boost::ptr_deque<Job>       m_JobsInProgress;
};

The question is: I don't want the Hardware to be accessible by any other class other than OS. Declaring Hardware private and friending OS is a step in the right direction, but it bothers me that OS now has access to all functions. Is there a way I can restrict OS?

Also, I did some researching on callbacks, but the C++ FAQ suggests that you shouldn't make callbacks to member functions of a class. Are there other solutions such that my Hardware class does not need a pointer to OS in order to call its functions?

Secondly, I'm wondering, at what point does the pImpl idiom become a viable solution? I mean, how large does a class have to be, or how many includes must it have, to seriously consider moving the class into a struct?

\$\endgroup\$
  • \$\begingroup\$ Boost.Signal also provides good tools for implementing callbacks. \$\endgroup\$ – Y G May 16 '11 at 16:51
8
\$\begingroup\$

That's not what friends are for. Friends are for tightly integrated classes which need to be able to play with each other's private data. OS and Hardware are not tightly related; they interact through a specifically designed interface.

If you don't want other classes besides OS to call the hardware functions, don't write code in those other classes which call the hardware functions. Better yet, simply only give the Hardware pointer to the OS class so only it can call the hardware functions.

For callbacks have a look at the boost::function library. It will allow you to create callbacks to the OS methods. You can create pointers to methods but you need both the method pointer and the object point for it to work. Boost::function hides all of this behind the scenes.

pImpl is workaround because C++ is such a silly language. Its purpose is to make it so that you do not have to recompile the header file whenever the private members of the class change. More modern languages essentially do this automatically for all classes. pImpl makes sense only when your compile times get too large. A class project probably doesn't get large enough for that to be a big concern.

\$\endgroup\$
  • \$\begingroup\$ I might have been confusing myself a little, but I wanted to protect my Hardware class from being accessed by another programmer. This friendship would have prevented other class from wrongfully calling Hardware. I was approaching this from a mentality, that a student would want to create changes to my design; this should have been a clear indicator to stay the hell away from my Hardware class. Do you agree with this assertion, or am I overcomplicating my design with this thinking? \$\endgroup\$ – IAE May 16 '11 at 16:06
  • \$\begingroup\$ @SoulBeaver, the question here is why you are trying to prevent students from making changes to your design. \$\endgroup\$ – Winston Ewert May 16 '11 at 17:04
  • 1
    \$\begingroup\$ @SoulBeaver: Think of what interface you want your Hardware class to have and write that, then do the same with OS. Having the OS take a pointer to an instance of a Hardware makes the relationship between them clear and allows for alternative implementations of both OS and Hardware to still reuse parts of your code. \$\endgroup\$ – dma May 16 '11 at 17:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.