bool operator idiom

Programming/C++ 2015. 2. 13. 11:45

http://en.wikibooks.org/wiki/More_C++_Idioms/Safe_bool


흐 - 음. 

선 기록 후 정리


struct Testable
{
    operator bool() const {
          return false;
    }
};
struct AnotherTestable
{
    operator bool() const {
          return true;
    }
};
int main (void)
{
  Testable a;
  AnotherTestable b;
  if (a == b) { /* blah blah blah*/ }
  if (a < 0) { /* blah blah blah*/ }
  // The above comparisons are accidental and are not intended but the compiler happily compiles them.
  return 0;
}


Solution


class Testable {
    bool ok_;
    typedef void (Testable::*bool_type)() const;
    void this_type_does_not_support_comparisons() const {}
  public:
    explicit Testable(bool b=true):ok_(b) {}
 
    operator bool_type() const {
      return ok_ ? 
        &Testable::this_type_does_not_support_comparisons : 0;
    }
};
template <typename T>
bool operator!=(const Testable& lhs, const T&) {
    lhs.this_type_does_not_support_comparisons();	
    return false;
}
template <typename T>
bool operator==(const Testable& lhs, const T&) {
    lhs.this_type_does_not_support_comparisons();
    return false;
}
class AnotherTestable ... // Identical to Testable.
{};
int main (void)
{
  Testable t1;
  AnotherTestable t2;
  if (t1) {} // Works as expected
  if (t2 == t1) {} // Fails to compile
  if (t1 < 0) {} // Fails to compile
 
  return 0;
}



In C++11, the explicit keyword can now be applied to conversion operators. As with constructors, it prevents the use of those conversion functions in implicit conversions. However, language contexts that specifically require a boolean value (the conditions of if-statements and loops, as well as operands to the logical operators) count as explicit conversions and can thus use a bool conversion operator.


struct Testable
{
    explicit operator bool() const {
          return false;
    }
};
 
int main()
{
  Testable a, b;
  if (a)      { /*do something*/ }  // this is correct
  if (a == b) { /*do something*/ }  // compiler error
}


0. App fundamentals

본문은 안드로이드 DevGuide 번역, 정리한 것입니다


http://developer.android.com/guide/components/fundamentals.html


Application Fundamental



  

* Android Java 언어로 구현.

* appt_tool 묶여져서(bundled) android package 구성, 확장자 .apk 가진다

* 어플리케이션은 각자의 리눅스 프로세스를 가진다.

* 프로세스는 virtual machine 지닌다.

* 어플리케이션은 고유한 리눅스 user ID 할당받는다. 기본적으로 어플리케이션의 파일들은 자신만 볼수 있지만 이에 접근하는 다른 방법도 있다.


Application Components




 다른 어플리케이션의 일부를 활용할 있도록 하기 위해(다른 사람이 개발한 유용한 파트를 내가 개발할 필요가 없다) 안드로이드는 main 대신에 다른 entry 보유하고 있다. 이것이 바로 Component 이다

컴포넌트는 다음과 같다.


Activity


 가시적인 유저 인터페이스. 액티비티는 그려야할 기본 윈도우를 지니고 있으며 추가적인 윈도우(예를 들어 팝업 윈도우) 지닐 수도 있다.

Activity 클래스를 extends 해서 구현.


Service 


 백그라운드에서 돌아감. 음악을 플레이한다거나네트워크를 통해 데이터를 가져온다거나 – …  Service클래스를 extends 해서 구현,


실행중인 서비스에 접속하는 것이나 실행시키는 것도 가능하다. 연결된 동안 서비스가 제공하는 인터페이스를 통해 통신할 있다


다른 컴포넌트와 마찬가지로 서비스도 어플리케이션 프로세스의 메인 스레드에서 구동된다. 다른 컴포넌트나 인터페이스를 방해하지 않기 위해서 , 많은 시간을 요하는 작업은 스레드를 통해 구성하는 편이 좋다.


Broadcast Receiver


방송을 수신. 컴포넌트를 통해 그에 적절한 응답을 있다

BroadcastReceiver extends 해서 구현. 방송에 대한 반응으로 필요에 따라 NotificationManager 클래스-LED 밝힌다거나 단말기가 진동한다든가의 작업을 있는 클래스- 이용할 있다.


Content Providers


 다른 어플리케이션에서 활용가능한 어플리케이션 데이터 집합을 구성.

파일 시스템이나 데이터베이스 , 다른 여러 공간에 저장될 있다직접 호출되지 않고 Content Resolver 통한다. 이것이 프로바이더와 내부 통신을 가능하게 한다




특정 컴포넌트의 요청을 수행해야 할때마다 컴포넌트가 수행되고 있음을 확인하고, 필요하면 실행시킨다. 그리고 적절한 인스턴스가 필요하다면 만든다.


Activating Components : intents




Content Resolver 요청할때 Content provider들이 활성화 된다. 다른 컴포넌트들은 인텐트에 의해서 호출된다. 인텐트 객체는 메시지의 내용을 보유하고 있으며, Activity Service 위해 요청되는 액션과 데이터들의 특정 URI 이름을 붙인다


컴포넌트를 활성화 시키는 방법들 :


1 . startActivity() .

2 . startService() . onStart() 서비스에서 호출됨. 이때 서비스 호출부,서비스 사이에서 인텐트가 bindService() 통해 넘겨 있다.

3 . sendBroadcast(), sendOrderedBroadcast(),  sendStickeyBroadcast() 여기에 인텐트를 전달하여 방송을 초기화할 수있다. 이때에 방송을 수신하는 리시버들의 onReceiver() 호출된다.  


Shutting Down Components


특정 요구에만 활성화되는 Contentprovider BroadcastReceiver 과는 다르게 Activity Service 더이상 쓸모가 없을때 개발자가 명시적으로 종료시켜줄 필요가 있다. 이때 사용하는 메서드는


  • finish() , finishActivity() – 2번째 메서드는 startActivityforResult() 생성한 액티비티를 호출한 액티비티에서만 호출가능. –
  • stopSelf() , stopService()



메모리가 필요할때는 메서드가 호출되지 않아도 시스템이 강제 종료할 수도 있다.


The manifest file




 안드로이드가 어플리케이션 컴포넌트를 실행시키기 위해 존재하는 컴포넌트들에 대한 정의를 해주는 파일. 퍼미션등의 설정도 이곳에서 이뤄진다. (AndroidManifest.xml)


엘리먼트로는 <activity> , <service> , <receiver> , <provider> 등이 있을 있다. 이중에 리시버는 동적으로 코드에서 정의 수도있다.


Intent filters


인텐트 객체가 명시적으로 타겟 컴포넌트를 나타내고 있을 수도 있지만, 그렇지 않을때는 안드로이드가 1.(인텐트 오브젝트) 2.(타겟이 있는 컴포넌트의 인텐트 필터) 비교해서 타겟을 결정해야한다. 인텐트 필터는 어떤 컴포넌트가 어떤 종류의 인텐트를 다룰 있는지를 나타내는 것이다. 이것 역시 manifest 파일에 정의된다.


Activity and Tasks


어플리케이션에서 다른 어플리케이션의 컴포넌트를 실행시키는 경우가 있을 있다. 실제로 다른 어플리케이션이지만, 사용자에게 이것이 하나의 어플리케이션인듯 자연스럽게 이해시킬 필요가 있다. 이를 위해 이용하는 것이 Task이다. (일종의 스택)


Task에서의 액티비티의 동작은 액티비티를 실행시키는 인텐트 객체의 flags set <activity> 엘리먼트의 attributes set 상호작용으로 구체화 된다.


flags attributes set 다음과 같다.


FLAG_ACTIVITY_NEW_TASK  -----

FLAG_ACTIVITY_CLEAR_TOP -----

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED -----

FLAG_ACTIVITY_SINGLE_TOP -----


taskAffinity -----

lanuchMode -----

allowTaskReparenting -----

clearTaskOnLaunch -----

alwaysRetainTaskState -----

finishOnTaskLaunch -----


: 액티비티는 액티비티를 호출한(startActivity) 액티비티와 같은 task 할당되는 것이 일반적인데 , startActivity 전달되는 인텐트가 플래그를 가지고 있다면 액티비티를 위해 새로운 task 찾는다. ( 완전 새로운 테스크를 할당하거나 액티비티와 어피니티() 같은 테스크에 할당하거나)


: 플래그를 가진 인텐트를 통해 액티비티가 새로 호출될때 이미 타겟 테스크에 인텐트를 다룰수있는 액티비티가 존재한다면 위에 있는 모든 액티비티를 버린다. 조합, 다른 테스크에 있는 존재하는 액티비티가 인텐트에 반응할 있도록 있다.


: <activity> 엘리먼트의 attribute. 가지 모드가 존재한다.

  • standard
  • singleTop
  • singleTask
  • singleInstance


  • 플래그가 없다면 모드일때 startActivity 인텐트의 테스크에 액티비티가 올라가게된다 모드의 액티비티는 여러 테스크에 소속될 수도 있고, 하나의 테스크가 액티비티의 인스턴스를 다수 가질 수도 있다. 여기까지는 2 같으며, 1 2 결정짓는 차이는 테스크의 탑에 이미 해당 인텐트를 처리할 있는 인스턴스가 있을때, 인스턴스를 재활용할지 혹은 새로운 인스턴스를 만들지이다.
  • 항상 테스크의 루트가 된다. 테스크에 오로지 하나의 인스턴스만이 존재할 있다. 모드에서는 어떤 인텐트의 요청이 있을때 이를 처리할 수있는 액티비티가 있으나 탑에 있지않을때에 그냥 인텐트를 버린다. (버리더라도 테스크가 포어그라운드로 오게 된다.)
  • 항상 테스크의 루트, 테스크에 하나의 인스턴스, 그러나 3과는 

다르게 테스크에 오로지 하나만 존재하게 된다. 항상 탑에 있기 때문에 인텐트의 요청에 반응한다.


: attribute true이면 , 그것이 시작한 테스크로부터 포어그라운드로 올라온 테스크에 어피니티가 있다면 테스크로 이동이 가능하다.


: 유저가 어떤 테스크를 멀리 떠나있다 돌아올때 , 어플리케이션의 초기상태로 돌아온다.


: 유저가 어떤 테스크를 떠나있다 돌아올때 , 아무일도 일어나지 않은 것처럼 테스크를 보존하고 있다.


: 일부만을 보존한다






Starting Tasks


Action “android.intent.action.MAIN” , category “android.intent.category.LAUNCHER” 설정하여 액티비티가 entry point 있도록 지정할 있다이러한 filter 액티비티 아이콘과 레이블이 어플리케이션 런쳐로 디스플레이 있도록 해줌와 동시에 task 실행할 있고 어느때건 실행된뒤에 되돌아 있는 방법을 제공한다.


두번째 기능은 중요하다 : 유저는 나중에라도 테스크를 떠나고 다시 되돌아 있다. 이러한 이유로, 테스크를 초기화 시키는  실행모드(launchmode)  - singleTask singleInstance – 반드시 해당 필터를 가지고 있을때만 사용 되어야 한다

필터들이 없을 때를 상상해보라! 하나의 인텐트가 singleTask 액티비티를 실행시키고, 새로운 Task 형성, 여기에서 사용자가 얼마간의 시간을 소모했다. 사용자가 홈키를 눌렀고, 사용자가 이용하던 테스크는 뒤로 밀려났다. 그리고 테스크는 런쳐가 아니기때문에 사용자가 다시 화면으로 돌아갈 방법이 없다


  • 유저가 되돌아왔을때 상태를 저장하기위해, singleTask singleInstance entry Activity 에서만 사용하라 !



launchMode 같이 새로운 테스크를 만드는 인텐트의 플래그 , FLAG_ACTIVITY_NEW_TASK 에도 비슷한 문제가 있다. 사용자가 되돌아 있도록 다른 방법을 강구해야된다. 어떤 엔티티는 (such as notification manager) 항상 외부 테스크로 액티비티를 실행킨다. 플래그가 항상 true 설정되어있다


사용자가 다시 되돌아가길 원하지 않는 케이스를 위해서는

finishOnTaskLaunch true 셋팅한다.




Processes and Threads 


어플리케이션에 처음으로 실행될때 안드로이드는 싱글스레드 리눅스 프로세스를 실행시킨다. 기본적으로 모든 컴포넌트들은 프로세스와 스레드에서 실행된다


하지만, 다른 프로세스에서 실행이 되도록 수정하는 것도 가능하며 아무프로세스에 추가적인 스레드를 구성하는 것도 가능하다.



Processes


Component 실행되는 프로세스는 메니페스트파일로 지정될 있다. 4 컴포넌트의 엘리멘트는 process 어트리뷰트를 가지고 있으며 이것으로 지정을 있다. 컴포넌트가 프로세스를 각각 가지고 있을지, 혹은 몇개만 공유하게 수도 , 심지어 다른 어플리케이션의 컴포넌트가 같은 프로세스에서 실행되는 것도 가능하다. – 같은 리눅스 유저아이디를 제공하고 같은 권한을 가지게 해서컴포넌트뿐만 아니라 <application>엘리먼트도 어플리케이션의 컴포넌트에 모두 적용되는 프로세스 속성을 가질수있다.



TCP/IP State Diagram

Theory 2015. 2. 9. 00:13

다음에 기반함


http://www.tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm


TCP/IP 의 커넥션은 상태에 따라 여러 스테이트로 생명주기를 관리한다.

이를 이해하면 어떻게 TCP 가 커넥션을 연결하고 - 그후 어떤 함수들이 호출되는지들에 대한 전반적인 개념을 잡을 수 있을 것이다. 


크게 3개의 메시지가 TCP 의 상태간 전이를 제어하고, 그 기능의 메시지를 제공함을 나타내는 TCP 헤더 플래그와 일치한다. 


* TCP 상태 전이를 제어하는 3개의 메시지


SYN : 연결을 맺고 초기화하는데 사용되는 동기(sync) 메시지. 다중의 디바이스간의 시퀀스를 동기화해주므로 이런 이름이 붙여졌다.

FIN : 만약 어떤 connection 이 이 비트를 세팅했다면, 연결을 종료하려는 것을 의미한다.

ACK : SYN 이나 FIN 의 수신을 나타내는 데 사용



에러컨디션 또한 상태의 전이를 야기할 수 있다. ( 하지만 이런 전이는 단순화된 스테이트 다이어그램에선 볼 수 없다. )



 State

상태 설명 

이벤트와 상태 전이 

CLOSED 

연결을 맺기위한 절차가 시작되기 전의 상태. 

"가상의" 상태로 일컬어 지는데, 단말간의 어떤 연결도 없음을 의미하기 때문이다 

- 생성되적도, 파괴된적도 없음을 의미한다- 

 수동 오픈 : 서버는 TCP 포트를 수동적으로 여는 것으로 연결과정을 시작한다. 

동시에, 연결을 관리하기 위해 필요한 데이터 구조를(transmission control block or TCB) 구성한다. 

이후 LISTEN 상태로 전이된다. 

 적극적 오픈, SYN 발송 : 클라이언트는 SYN 메시지를 발송하는 것으로 연결을 시작하고, TCB 를 구성한다. 

그 후 SYN-SENT 상태로 전이된다. 

 LISTEN

장치(보통 서버)는 SYN 메시지를 클라이언트로부터 수신되기를 기다린다. 

아직, 본인은 SYN 메시지를 보낸적이 없다.  

 클라이언트의 SYN 메시지를 수신하고, SYN+ACK 발송 : 

서버 장치는 클라이언트로 부터 수신하여 SYN 과 응답을 다시 발송처로 전달한다. 

이제 서버는 SYN-RECIEVED 상태로 전이 된다. 

 SYN-SENT

장치(보통 클라이언트) 는 SYN 메시지를 보냈고 

이에 맞는 SYN 메시지를 다른 장치(보통 서버)로부터 기다린다.  

 SYN 수신, ACK 발송 : 만약 이 장치가 SYN 메시지를 받았지만 ACK 메시지를 받지 못한 경우, 

SYN-RECEIVED 상태로 전이되고 ACK 을 기다린다. 

 SYN + ACK 수신, ACK 발송 : 만약 둘다 수신이 되면, ESTABLISHED 상태로 전이된다. 

 SYN-RECEIVED

 장치는 SYN 를 보내기도 했고, 파트너로부터 SYN 를 받기도 했다. 이제 연결요청인 SYN 가 연결 준비를 모두 마치기 위해 ACK 을 기다린다.  

 ACK 수신 : ESTABLISHED 상태로 전이

 ESTABLISHED

TCP 커넥션을 오픈하는 '꾸준한 상태'. 

양쪽 장치 사이에서 자유롭게 데이터를 주고받을 수 있다. 

커넥션이 종료되기 전까지 지속된다.  

 종료, FIN 전송 : 장치는 FIN 메시지를 발송 함으로써 연결을 종료할 수 있다. FIN-WAIT-1 상태로 전이.

 FIN 수신 : 커넥션 상대로부터 연결 종료를 요청하는 FIN 메시지를 수신할 수 있다. CLOSE-WAIT 상태로 전이된다. 

 CLOSE-WAIT

장치가 FIN 요청을 상대로부터 받았다. 어플리케이션이 이 요청을 처리하기를, 이를 위한 요청을 구성하는 것을 기다린다.  

 종료, FIN 발송 : TCP 를 사용하는 어플리케이션은 다른 프로세스들에게 셧다운을 하고 싶음을 알리며, 연결종료 요청을 TCP 레이어에 전송한다. TCP 는 FIN 메시지를 원격 장치에 전송하고, 이 장치는 이제 LAST-ACK 상태로 전이된다. 

 LAST-ACK

 장치는 연결 종료요청을 수신하고 이를 인지하여 FIN 요청을 발송하고 이에 따른 ACK 을 대기하고 있다.

 FIN 에 대한 ACK 수신 : 장치는 연결 종료요청을 인지했다. FIN 메시지를 이에 따라 응답으로 전송했으며, 

ACK 을 수신하면 CLOSED 상태로 전이된다.  

 FIN-WAIT-1

장치는 FIN 을 발송하고 ACK 의 수신을 기다리고 있다. 혹은 다른 장치의 연결 종료 요청을 기다리고 있다.  

 FIN 에 대한 ACK 수신 : 장치는 연결 종료대한 응답을 수신했다. FIN-WAIT-2 상태로 전이.

 FIN 을 수신하고 ACK 을 발송 : 장치는 자신이 발송한 FIN 에 대한 ACK 을 받지 못하였지만 FIN 을 그 디바이스로부터 전송받았다. 이를 인지하여 CLOSING 상태로 전이된다. 

 FIN-WAIT-2

장치는 ACK 을 그것의 연결종료 요청에 대한 응답으로 수신하였으며 

이제 상대 장치로부터 일치하는 FIN 메시지를 기다리고 있다.  

 FIN 을 수신, ACK 발송 : 장치는 FIN 을 상대 디바이스로부터 전달 받았다. 이를 인지하여 TIME-WAIT 상태로 전이된다. 

CLOSING 

장치는 FIN 을 수신하여 ACK 를 응답으로 전송하였지만, 

그것이 요청한 FIN 메시지에 대해서는 ACK 를 받지 못하였다.  

 ACK 을 FIN 에 대한 응답으로 수신 : 장치는 연결 종료 요청에 대한 응답을 받았다. TIME-WAIT 상태로 전이된다.

TIME-WAIT 

장치는 FIN 메시지를 다른 장치로부터 수신하여, 그것의 FIN 메시지를 발송하여 ACK 메시지를 전달 받았다. ACK 이 새로운 연결에 의해 잠재적으로 덮어지는 예외 상황을 제외하면 모든 과정이 완료되었다. 

( 이 상태에 대해 좀더 알고 싶다면 다음을 참고하라. the topic describing connection termination ) 

 타이머만료 : 지정된 시간만큼 대기한후, 장치상태는 CLOSED 상태로 전이된다. 



'Theory' 카테고리의 다른 글

Neuron Network - Supervised  (2) 2010.11.04