Out-of-Process 서버 구현 도우미
Out-of-process 서버에서 호출할 수 있는 4개의 도우미 함수를 사용하여 서버 코드 작성 작업을 간소화할 수 있습니다. COM 클라이언트 및 COM In-Process 서버는 일반적으로 이를 호출하지 않습니다. 이러한 함수는 서버에 아파트 또는 여러 클래스 개체가 있는 경우 서버 정품 인증 시 경합 상태를 방지하도록 설계되었습니다. 그러나 단일 스레드 및 단일 클래스 개체 서버에 쉽게 사용할 수도 있습니다. 함수는 다음과 같습니다.
제대로 종료하려면 COM 서버가 인스턴스화한 개체 인스턴스 수와 IClassFactory::LockServer 메서드가 호출된 횟수를 추적해야 합니다. 이 두 개수가 모두 0에 도달한 경우에만 서버를 종료할 수 있습니다. 단일 스레드 COM 서버에서 종료 결정은 메시지 큐에 의해 직렬화된 들어오는 활성화 요청과 조정되었습니다. 서버는 최종 개체 instance 릴리스를 받고 종료하기로 결정하면 더 이상 활성화 요청이 디스패치되기 전에 클래스 개체를 해지합니다. 이 시점 이후에 활성화 요청이 들어온 경우 COM은 클래스 개체가 해지되었음을 인식하고 SCM(Service Control Manager)에 오류를 반환합니다. 그러면 로컬 서버 프로세스의 새 instance 실행됩니다.
그러나 서로 다른 클래스 개체가 서로 다른 아파트에 등록되어 있는 아파트 모델 서버와 모든 무료 스레드 서버에서 이 종료 결정은 서버의 한 스레드가 클래스 개체 또는 개체 인스턴스를 전달하는 동안 서버의 한 스레드가 종료되지 않도록 여러 스레드에서 활성화 요청과 조정되어야 합니다. 이 문제를 해결하는 한 가지 클래식적이지만 번거로운 접근 방식은 서버가 클래스 개체를 취소한 후 instance 개수를 다시 검사하고 모든 인스턴스가 해제될 때까지 활성 상태를 유지하는 것입니다.
서버 작성기가 이러한 유형의 경합 조건을 더 쉽게 처리할 수 있도록 COM은 두 가지 참조 계산 함수를 제공합니다.
- CoAddRefServerProcess는 전역 프로세스별 참조 수를 증분합니다.
- CoReleaseServerProcess는 프로세스별 전역 참조 수를 감소합니다.
전역 프로세스별 참조 수가 0에 도달하면 COM은 자동으로 CoSuspendClassObjects를 호출하여 새 활성화 요청이 들어오지 않도록 합니다. 그런 다음 서버는 다른 활성화 요청이 들어올 수 있다는 걱정 없이 여가 시간에 다양한 스레드에서 다양한 클래스 개체의 등록을 취소할 수 있습니다. 모든 새 활성화 요청은 이제부터 로컬 서버 프로세스의 새 instance 시작하는 SCM에 의해 처리됩니다.
로컬 서버 애플리케이션에서 이러한 함수를 사용하는 가장 간단한 방법은 fLock 매개 변수가 TRUE인 경우 각 instance 개체 및 각 IClassFactory::LockServer 메서드에 대해 생성자에서 CoAddRefServerProcess를 호출하는 것입니다. 또한 서버 애플리케이션은 fLock 매개 변수가 FALSE인 경우 각 instance 개체의 소멸자 및 각 IClassFactory::LockServer 메서드에서 CoReleaseServerProcess를 호출해야 합니다.
마지막으로 서버 애플리케이션은 CoReleaseServerProcess의 반환 코드에 주의를 기울여야 하며, 0을 반환하는 경우 서버 애플리케이션은 정리를 시작해야 합니다. 즉, 여러 스레드가 있는 서버의 경우 일반적으로 다양한 스레드가 메시지 루프를 종료하고 CoAddRefServerProcess 및 CoReleaseServerProcess를 호출하도록 신호를 보내야 합니다. 서버 프로세스 수명 관리 함수를 사용하는 경우 개체 인스턴스와 LockServer 메서드 모두에서 사용해야 합니다. 그렇지 않으면 서버 애플리케이션이 조기에 종료될 수 있습니다.
CoGetClassObject 요청이 수행되면 COM은 서버에 연결하고, 클래스 개체의 IClassFactory 인터페이스를 마샬링하고, 클라이언트 프로세스로 반환하고, IClassFactory 인터페이스를 언마샬링하고, 이를 클라이언트에 반환합니다. 이 시점에서 클라이언트는 일반적으로 서버 프로세스가 종료되지 않도록 TRUE를 사용하여 LockServer를 호출합니다. 그러나 클래스 개체가 마샬링되는 시점과 클라이언트가 LockServer를 호출하는 시점 사이에는 다른 클라이언트가 동일한 서버에 연결하고, instance 가져오고, 해당 instance 해제하므로 서버가 종료되고 첫 번째 클라이언트가 연결이 끊긴 IClassFactory 포인터로 높고 건조한 상태로 남게 됩니다. 이 경합 상태를 방지하기 위해 COM은 IClassFactory 인터페이스를 마샬링할 때 클래스 개체에 TRUE가 있는 LockServer에 암시적 호출을 추가하고 클라이언트가 IClassFactory 인터페이스를 해제할 때 FALSE를 사용하여 LockServer를 암시적으로 호출합니다. 따라서 LockServer 를 원격으로 서버로 다시 호출할 필요는 없으며 LockServer 의 프록시는 실제로 호출을 원격하지 않고 S_OK 반환합니다.
Out-of-process 서버 프로세스를 초기화하는 동안 또 다른 활성화 관련 경합 상태가 있습니다. 여러 클래스를 등록하는 COM 서버는 일반적으로 지원하는 각 CLSID에 대한 REGCLS_LOCAL_SERVER 사용하여 CoRegisterClassObject 를 호출합니다. 모든 클래스에 대해 이 작업을 수행한 후 서버는 메시지 루프를 입력합니다. 단일 스레드 COM 서버의 경우 서버가 메시지 루프에 들어갈 때까지 모든 활성화 요청이 차단됩니다. 그러나 다른 아파트 및 모든 무료 스레드 서버에 대해 서로 다른 클래스 개체를 등록하는 아파트 모델 서버의 경우 활성화 요청이 이보다 일찍 도착할 수 있습니다. 아파트 모델 서버의 경우 한 스레드가 메시지 루프를 입력하는 즉시 활성화 요청이 도착할 수 있습니다. 자유 스레드 서버의 경우 첫 번째 클래스 개체가 등록되는 즉시 활성화 요청이 도착할 수 있습니다. 활성화는 이 초기에 발생할 수 있으므로 서버의 나머지 부분의 초기화를 완료하기 전에 최종 릴리스가 발생할 수도 있습니다(따라서 서버가 종료되기 시작).
이러한 경합 조건을 제거하고 서버 작성기의 작업을 간소화하려면 COM에 여러 클래스 개체를 등록하려는 서버는 REGCLS_LOCAL_SERVER CoRegisterClassObject 를 호출해야 합니다. 서버에서 지원하는 서로 다른 각 CLSID에 대해 REGCLS_SUSPENDED. 모든 클래스가 등록되고 서버 프로세스가 들어오는 활성화 요청을 수락할 준비가 되면 서버는 CoResumeClassObjects를 한 번 호출해야 합니다. 이 함수는 COM에 등록된 모든 클래스에 대해 SCM에 알리도록 지시하고 서버 프로세스에 활성화 요청을 허용하기 시작합니다. 이러한 함수를 사용하면 다음과 같은 이점이 있습니다.
- 등록된 CLSID 수에 관계없이 SCM에 대한 호출이 하나만 이루어지므로 전체 등록 시간(따라서 서버 애플리케이션의 시작 시간)이 줄어듭니다.
- 서버에 아파트가 여러 개 있고 다른 CLSID가 다른 아파트에 등록되어 있거나 서버가 무료 스레드 서버인 경우 서버가 CoResumeClassObjects를 호출할 때까지 활성화 요청이 들어오지 않습니다. 그러면 서버가 모든 CLSID를 등록하고 활성화 요청 및 가능한 종료 요청을 처리하기 전에 제대로 설정될 수 있습니다.
관련 항목