PSerial.h
#pragma once
#include <ace/Asynch_IO.h>
#include <ace/TTY_IO.h>
#include <ace/Message_Queue.h>
#include <ace/Synch.h>
#include <ace/Proactor.h>
class PSerial:public ACE_Handler
{
public:
PSerial(ACE_Proactor* actor, const char* pname);
~PSerial(void);
int write( const char* data);
private:
virtual void handle_read_file (const ACE_Asynch_Read_File::Result &result);
virtual void handle_write_file (const ACE_Asynch_Write_File::Result &result);
private:
ACE_TTY_IO serial_port_;
ACE_Asynch_Read_File read_require_;
ACE_Message_Block read_msg_;
ACE_Asynch_Write_File write_require_;
ACE_Atomic_Op<ACE_Thread_Mutex, bool> writable_;
ACE_Message_Queue<ACE_MT_SYNCH> write_msg_queue_;
private:
void read_();
};
PSerial.cpp
#include "PSerial.h"
#include <ace/DEV_Connector.h>
#include <iostream>
PSerial::PSerial(ACE_Proactor* actor, const char* pname)
:ACE_Handler(actor),read_msg_(4096),writable_(true)
{
ACE_DEV_Connector con;
con.connect(this->serial_port_,ACE_DEV_Addr(pname),0,ACE_Addr::sap_any,0,O_RDWR|FILE_FLAG_OVERLAPPED);
ACE_TTY_IO::Serial_Params myparams;
myparams.baudrate = 9600;
myparams.paritymode = "EVEN";
myparams.databits = 8;
myparams.stopbits = 1;
myparams.readtimeoutmsec = 50;
myparams.rtsenb = 1;//RTS
myparams.ctsenb = 0;//CTS
myparams.dtrdisable = 1;//DTR
myparams.dsrenb = 1;//DSR
this->serial_port_.control( ACE_TTY_IO::SETPARAMS, &myparams);
this->read_require_.open(*this,this->serial_port_.get_handle(), 0, this->proactor());
this->write_require_.open(*this,this->serial_port_.get_handle(), 0, this->proactor());
this->read_();
}
PSerial::~PSerial(void)
{
this->read_require_.cancel();
this->write_require_.cancel();
this->serial_port_.close();
}
void
PSerial::read_(){
this->read_msg_.reset();
this->read_require_.read( this->read_msg_, this->read_msg_.space());
}
void
PSerial::handle_read_file (const ACE_Asynch_Read_File::Result &result){
if( ! result.success() ){
std::cout<<std::endl<<"Error:"<<result.error();
this->read_();
return;
}
if( 0 == result.bytes_transferred()){
this->read_();
return;
}
std::cout<<std::endl<<"RECV size:"<< result.bytes_transferred();
this->read_();
}
int
PSerial::write( const char* data){
size_t len= ACE_OS::strlen(data)+1;
if( 1==len) return 0;
ACE_Message_Block* m;
ACE_NEW_RETURN(m, ACE_Message_Block(len), -1);
m->copy(data);
m->wr_ptr(-1);
if( this->writable_.value()){
this->writable_=false;
return this->write_require_.write(*m, m->length());
}
return this->write_msg_queue_.enqueue_tail(m);
}
void
PSerial::handle_write_file (const ACE_Asynch_Write_File::Result &result){
if(!result.success()){
this->write_require_.write( result.message_block(), result.message_block().length());
std::cout<<std::endl<<"Error:"<<result.error();
return;
}
if( 0 == result.message_block().length()){
result.message_block().release();
if( this->write_msg_queue_.is_empty()){
this->writable_ =true;
return;
}
ACE_Message_Block* m;
this->write_msg_queue_.dequeue(m);
this->write_require_.write( *m, m->length());
return;
}
this->write_require_.write( result.message_block(), result.message_block().length());
}
Serial_Proactor.cpp
// Serial_Proactor.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <ace/ACE.h>
#include "PSerial.h"
#include <iostream>
#include <string>
#include <ace/Thread_Manager.h>
ACE_THR_FUNC_RETURN fn(void *arg){
PSerial* pf = (PSerial*) arg;
std::string cmd;
while(true){
std::cout<<std::endl<<"시리얼로 보낼 데이터를 입력하세요. 종료시 exit를 입력하세요."<<std::endl;
std::getline( std::cin, cmd);
if("exit"==cmd) break;
for( int i=0 ;i<1024;++i){
pf->write( cmd.c_str());
}
}
ACE_Proactor::instance()->proactor_end_event_loop();
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
ACE::init();
{
PSerial pf(ACE_Proactor::instance(), "COM1");
ACE_Thread_Manager tm;
tm.spawn(fn,&pf);
ACE_Proactor::instance()->proactor_run_event_loop();
tm.wait();
}
ACE::fini();
return 0;
}