00001
00007 #include <typeinfo>
00008 #include <sstream>
00009 #include <cerrno>
00010
00011 #include <Utilitarios/cadeia.H>
00012
00013
00014 inline IPC::Erro::Erro(std::string const& mensagem)
00015 : Erros::Erro(mensagem)
00016 {
00017 }
00018
00019 inline IPC::Erro::Erro()
00020 : Erros::Erro(std::string("Erro IPC: \"") + strerror(errno) + '"')
00021 {
00022 }
00023
00024
00025
00026 inline std::string IPC::Mensageiro::meuIdentificador() const
00027 {
00028 using namespace Utilitarios;
00029
00030 passwd* info = getpwuid(meu_UID);
00031 return std::string(info->pw_name) + " (" + meu_PID + ')';
00032 }
00033
00034 inline std::string IPC::Mensageiro::identificadorDoOutro() const
00035 {
00036 using namespace Utilitarios;
00037
00038 passwd* info = getpwuid(UID_do_outro);
00039 return std::string(info->pw_name) + " (" + PID_do_outro + ')';
00040 }
00041
00042 inline void IPC::Mensageiro::leMensagem()
00043 {
00044 tipo_dos_dados = leBasico(meu_PID);
00045 mensagem = leBasico(meu_PID);
00046 }
00047
00048 template <typename Tipo>
00049 inline Tipo const IPC::Mensageiro::mensagemLida() const
00050 {
00051 if(typeid(Tipo).name() != tipo_dos_dados)
00052 throw Erro("Conversão de mensagem de " + tipo_dos_dados + " para " +
00053 typeid(Tipo).name() + " impossível!");
00054
00055 std::istringstream entrada(mensagem);
00056 Tipo valor;
00057 entrada >> valor;
00058 if(not entrada.good() and not entrada.eof())
00059 throw Erro("Problema na extracção da mensagem!");
00060
00061 return valor;
00062 }
00063
00064
00065
00066 template <>
00067 inline std::string const IPC::Mensageiro::mensagemLida<std::string>() const
00068 {
00069 if(typeid(std::string).name() != tipo_dos_dados)
00070 throw Erro("Conversão de mensagem de " + tipo_dos_dados + " para " +
00071 typeid(std::string).name() + " impossível!");
00072
00073 return mensagem;
00074 }
00075
00076 template <typename Tipo>
00077 inline void IPC::Mensageiro::envia(Tipo& mensagem) const
00078 {
00079 std::ostringstream saida;
00080 saida << mensagem;
00081
00082 if(not saida.good())
00083 throw Erro("Problema ocorreu durante a inserção da mensagem!");
00084
00085 escreveBasico(PID_do_outro, typeid(Tipo).name());
00086 escreveBasico(PID_do_outro, saida.str());
00087 }
00088
00089 template <typename Tipo>
00090 inline void IPC::Mensageiro::envia(Tipo const& mensagem) const
00091 {
00092 std::ostringstream saida;
00093 saida << mensagem;
00094
00095 if(not saida.good())
00096 throw Erro("Problema ocorreu durante a inserção da mensagem!");
00097
00098 escreveBasico(PID_do_outro, typeid(Tipo).name());
00099 escreveBasico(PID_do_outro, saida.str());
00100 }
00101
00102 template <typename Char>
00103 inline void IPC::Mensageiro::envia(Char const*& mensagem) const
00104 {
00105 envia(std::basic_string<Char>(mensagem));
00106 }
00107
00108 template <typename Char>
00109 inline void IPC::Mensageiro::envia(Char const* const& mensagem) const
00110 {
00111 envia(std::basic_string<Char>(mensagem));
00112 }
00113
00114 template <typename Char>
00115 inline void IPC::Mensageiro::envia(Char* const& mensagem) const
00116 {
00117 envia(std::basic_string<Char>(mensagem));
00118 }
00119
00120 template <typename Char>
00121 inline void IPC::Mensageiro::envia(Char*& mensagem) const
00122 {
00123 envia(std::basic_string<Char>(mensagem));
00124 }
00125
00126 template <typename Char, int dimensao>
00127 inline void
00128 IPC::Mensageiro::envia(Char const (& mensagem)[dimensao]) const
00129 {
00130 envia(std::basic_string<Char>(mensagem));
00131 }
00132
00133 inline int IPC::Mensageiro::leBasicoInt(int const tipo,
00134 bool const deve_esperar) const
00135 {
00136 std::istringstream entrada(leBasico(tipo, deve_esperar));
00137
00138 int valor;
00139 entrada >> valor;
00140
00141 if(not entrada.good() and not entrada.eof())
00142 throw Erro("Problema na extracção da mensagem!");
00143
00144 return valor;
00145 }
00146
00147 inline void IPC::Mensageiro::escreveBasicoInt(int const tipo, int const valor)
00148 {
00149 std::ostringstream saida;
00150
00151 saida << valor;
00152
00153 if(not saida.good())
00154 throw Erro("Problema ocorreu durante a inserção da mensagem!");
00155
00156 escreveBasico(tipo, saida.str());
00157 }
00158
00159 inline void IPC::Mensageiro::estabeleceCaixaDoCorreio(key_t const chave)
00160 {
00161
00162
00163 int permissoes = (chave == key_t(getuid()))? 0660 : 0666;
00164
00165
00166
00167 identificador_da_caixa_do_correio = msgget(chave, IPC_CREAT | permissoes);
00168 if(identificador_da_caixa_do_correio == -1)
00169 throw Erro();
00170 }
00171
00172 inline void IPC::Mensageiro::removeCaixaDoCorreio()
00173 {
00174 msgctl(identificador_da_caixa_do_correio, IPC_RMID, 0);
00175 }
00176
00177 inline void IPC::Mensageiro::entraEmAcessoExclusivo() const
00178 {
00179 sembuf vermelho = {0, -1, 0};
00180
00181 if(semop(identificador_do_semaforo, &vermelho, 1) == -1)
00182 throw Erro();
00183 }
00184
00185 inline void IPC::Mensageiro::saiDeAcessoExclusivo() const
00186 {
00187 sembuf verde = {0, 1, 0};
00188
00189 if(semop(identificador_do_semaforo, &verde, 1) == -1)
00190 throw Erro();
00191 }
00192
00193 inline bool IPC::Mensageiro::cumpreInvariante() const
00194 {
00195 return meu_PID == int(getpid()) and meu_UID == int(getuid()) and
00196 0 <= identificador_da_caixa_do_correio and
00197 0 <= identificador_do_semaforo;
00198 }